2017-10-31 13 views
0

ループ内にオブジェクトを作成しようとしています。私aFunctionCreatesParseObjectAndSave(ID)機能でParse Serverで重複するエントリを作成する

myarray=[1,1,1,1,1]; 

for (var k = 0; k < myarray.length; k++){ 
     var id = myarray[k]; 
     aFunctionCreatesParseObjectAndSave(id); 
} 

、私は私が同じIDを持つ解析オブジェクトを持っている場合ということをチェックしようとしています。 (parsequeryと見て)私はそれを作成していない場合は、ちょうど更新します。しかし、オブジェクトがない場合はそれを作成し、保存します。

function aFunctionCreatesParseObjectAndSave(id){ 
    var query= new Parse.Query(MyParseObject); 
    query.equalTo("myId",id); 

    query.first().then(
     function(result){ 
       if(result === undefined){ 
        // there isn't entry for this id 
        //create parseObject and fill it 
        ... 
         newObject.set("id",id); 
         newObject.save(); 
       }else{ 
         // entry found for this id 
         //do update on result and save 
         ... 
         result.save(); 
       } 
     } 
    ); 

} 

私のテスト配列(すべての要素は同じIDです)では、ただ1つのエントリを作成する必要があります。しかし、私はmyarray.lengthカウントオブジェクト:(私はこの問題を解決するにはどうすればよい

+0

注意すべきことは、誤字があることです。 'newId'を探していますが、' id 'を設定しています。それが起こると、あなたは私の答えで説明する約束のまわりでより基本的な問題を抱えています。 –

答えて

0

約束を持っている!

本当に短い答えは、あなたが何かが存在するかどうかを確認するために、行に5回をチェックしているということです第一の目的は、これまでに保存される前に。

今長い答えのため、[OK]をクリックします。

あなたのループがaFunctionCreatesParseObjectAndSaveを呼び出します。機能はそのものを行いますが、それはそのようなものを行うにするためにループは待ちませんザクエリとtの保存オブジェクトは非同期であるため、関数は呼び出したクエリが実行を続けていてもすぐに「返されます」。

うまくいけば、私は何が起こっていることを明確にすることができます。

  1. 私はどのようにあなたを紹介します
  2. に何が起こっている「証明」されますあなたのコードにマイナーな調整を行います約束の良さをもってそれをすること。
  3. 最後に、一意のIDを使用する場合は、バッキングストアに一意のインデックスを追加してください(mongo?)。

商品一覧はこちら最初のコードは、多かれ少なかれ、あなたのコードに加えて、うまくいけば何が起こっているかを示すために最後のテストとユニットテストです....

以下
// testing boilerplate 2 lines... 
describe('my test',() => { 
    it('count', (done) => { 
    // ok, this is all "our code"   
    const MyParseObject = 'TestClass'; 

    // a function to count number of records with a given id. 
    // Importantly, this function returns a promise. 
    const count = function count(id) { 
     return new Parse.Query(MyParseObject) 
     .equalTo('myId', id) 
     .count(); // <-- count returns a promise 
    } 

    // your function with all the ...'s filled in. 
    function aFunctionCreatesParseObjectAndSave(id){ 
     var query = new Parse.Query(MyParseObject); 
     query.equalTo("myId",id); 
     query.first().then(
     function(result){ 
      if(result === undefined){ 
      // there isn't entry for this id 
      //create parseObject and fill it 
      const newObject = new Parse.Object(MyParseObject); 
      newObject.set('myId',id); 
      // you don't wait for this promise to resolve! 
      newObject.save(); 
      } else { 
      // entry found for this id 
      // do update on result and save 
      result.increment('count'); 
      // this never gets called, and is never waited on... 
      result.save(); 
      } 
     }); 
    } 

    const myarray = [1,1,1,1,1]; 

    for (var k = 0; k < myarray.length; k++){ 
     var id = myarray[k]; 
     aFunctionCreatesParseObjectAndSave(id); 
    } 

    // so what I'm doing here is waiting for 
    // 1 second, then counting the number 
    // of records with the same 'myId'. 
    // and then testing that each id in the array 
    // got a new object. 
    setTimeout(() => { 
     count(id) 
     // count will be 5 and that's one per element in myarray 
     .then(count => expect(count).toBe(myarray.length)) 
     .then(done) 
     .catch(done.fail) 
    }, 1000); // 1,000 miliseconds is one second 
    }); 
}); 

どのように私です1つのオブジェクトを作成するだけでなく、各繰り返しでカウンタをインクリメントするようにコードを「修正」しました。

describe('my test',() => { 
    const MyParseObject = 'TestClass'; 

    it('count', (done) => { 
    // This will call an array of functions that return promises in sequence. 
    const sequence = function sequence(tasks) { 
     return tasks.reduce((promise, task) => promise.then(() => task.call()), Promise.resolve()); 
    } 

    function aFunctionCreatesParseObjectAndSave(id){ 
     var query = new Parse.Query(MyParseObject); 
     query.equalTo("myId",id); 

     // Very important to return this promise! 
     return query.first().then(
     function(result){ 
      if(result === undefined){ 
      // there isn't an entry for this id 
      //create parseObject and fill it 
      const newObject = new Parse.Object(MyParseObject); 
      newObject.set('myId', id); 
      newObject.set('count', 1); 
      // very important to return this promise! 
      return newObject.save(); 
      } else { 
      // entry found for this id 
      //do update on result and save 
      result.increment('count'); 
      // very important to return this promise! 
      return result.save(); 
      } 
     }); 
    } 

    const myarray = [1,1,1,1,1]; 
    const promises = []; 
    for (var k = 0; k < myarray.length; k++){ 
     var id = myarray[k]; 
     // don't call the function, make an array of functions that call the functions. 
     promises.push(() => aFunctionCreatesParseObjectAndSave(id)); 
    } 

    // We have an array promises that haven't even started to run. 
    // the function sequence() will now execute each promise 
    // in the array, then wait till its done and start the next 
    // promise. 
    sequence(promises) 
     .then(() => new Parse.Query(MyParseObject).find()) 
     .then(results => { 
     // this test verifies that there is only one object now. 
     expect(results.length).toBe(1); 
     const theObj = results[0]; 
     // the count member of the object should be 5, one for each 
     // id element of 1 in 'myarray' 
     expect(theObj.get('count')).toBe(myarray.length); 
     done(); 
     }) 
     .catch(done.fail); 
    }); 
}); 

ここで行ったテストは、nodejsサーバーで単体テストを実行するコンテキストです。そして私はsequence関数を書いた。 「実生活で」、特にこのコードがブラウザで実行されている場合は、ブルーバードのようなライブラリを使用してからmapSeriesを使用したいと考えています。

関連する問題