2016-09-06 16 views
0

モバイルコード/角度プロジェクトで作業しています。以下は、単純なサービスコールは、次のとおりです。非同期と同期の問題を約束します

this.getSomeData = function (businessId) { 
    var deferred = $q.defer(); 
    var query = "SELECT * FROM Stuff"; 
    $cordovaSQLite.execute(db, query).then(function (res) { 
     deferred.resolve(res.rows); 
    }, function (err) { 
     deferred.reject(err); 
    }); 

    return deferred.promise; 
}; 

問題は単純です:

for (var k = 0; k < count; k++) { 

    myService.getSomeData($scope.model.stuff[k].id, k).then(function (data) { 
     // whatever 
    } 
); 

getSomeDataは、それが返す時間によってので、forサイクルのkが正しいから遠い、非同期です。

私は、パラメータとしてサービスメソッドにkを渡すと思った:

for (var k = 0; k < count; k++) { 

    myService.getSomeData($scope.model.stuff[k].id, k).then(function (data) { 
     // whatever 
    } 
); 

し、それに応じてサービスメソッドを変更:

this.getSomeData = function (id, index) { 
    var deferred = $q.defer(); 
    var query = "SELECT * FROM Stuff"; 
    $cordovaSQLite.execute(db, query).then(function (res) { 
     deferred.resolve(res.rows, index); 
    }, function (err) { 
     deferred.reject(err); 
    }); 

    return deferred.promise; 
}; 

しかし、二番目のパラメータは無視され、常に定義されていないされていることを。

これを解決するにはどうすればよいですか?

+2

まず、(http://stackoverflow.com/q/23803743/1048572)[繰延アンチパターンを避ける] – Bergi

+0

@JLRisheなぜあなたはこれを再度開くのですか? – Bergi

+0

@Bergiあなたが指摘した質問は、この問題に対する答えではないためです。答えは '$ q.all()'です。 – JLRishe

答えて

0

これは私がそれを動作させる方法です。 @ JLRisheの提案を使ってみましたが、うまくいきませんでした。私は、複数のパラメータをサービスメソッドに渡して、コントローラに戻すこともできました(必要な数だけ必要なパラメータを含むオブジェクトを構築することによって)。すべての

myService.getSomeData().then(
    function (stuff) { 
     // whatever 
    } 
).then(function() { 
    for (var i = 0; i < $scope.model.stuff.length; i++) { 

     // HERE I SEND TWO PARAMETERS TO THE SERVICE METHOD 
     myService.getSomeMoreData($scope.model.stuff[i].id, i).then(
      function (data) { 
       // whatever 
      } 
     ); 
    } 
}); 

this.getSomeMoreData = function (id, index) { 
    var deferred = $q.defer(); 
    var query = "SELECT * FROM stuff"; 

    $cordovaSQLite.execute(db, query).then(function (res) { 
     var moreStuff = []; 

     for (var i = 0; i < res.rows.length; i++) { 
      var junk = res.rows.item(i); 
      moreStuff.push(junk); 

     } 

     // HERE I RESOLVE AN OBJECT INSTEAD OF TWO PARAMETERS 
     deferred.resolve({ 
      moreStuff: moreStuff, 
      index: index 
     }); 

    }, function (err) { 
     deferred.reject(err); 
    }); 

    return deferred.promise; 
}; 
0

それはあなたが「ループ変数の上に閉鎖」と呼ばれ、この問題はここでは詳細に記載されている問題に実行しているように聞こえる:あなたのケースでは

JavaScript closure inside loops – simple practical example

、しかし、きれいな解決策があります$q.all()Array#mapを組み合わせること:Bergiが指摘するように

また
$q.all($scope.model.visits.map(function (stuff) { 
    return myService.getSomeData(stuff.id); 
})).then(function (results) { 
    // results is an array of the results of all the calls to getSomeData() in the correct order 
}); 

を、deferred antipatternを避ける:

this.getSomeData = function (id) { 
    var query = "SELECT * FROM Stuff"; 

    return $cordovaSQLite.execute(db, query).then(function (res) { 
     return res.rows; 
    }); 
}; 
+0

なぜ 'deferred.resolve'ではなく' return'ですか? – chiapa

+1

@chiapaこれは約束が働く方法なので、4行短くなり、人為的ミスの余地が少なくなります。 – JLRishe

+0

私は 'promisesArray.push(myService.getSomeData($ scope.model.stuff [k] .id));'を実行したので、配列内に値を格納しています。今、私はそれらのすべてが走ったら、それらにアクセスしたいですね。 – chiapa