2016-09-06 125 views
0

在移動cordova /角項目上工作。下面是一個簡單的服務電話:承諾與異步和同步問題 - 角

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($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 
}); 

,爲BERGI指出,避免deferred antipattern:到Array#map$q.all()結合

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

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

爲什麼'return'而不是'deferred.resolve'? – chiapa

+1

@chiapa因爲承諾是如何工作的,所以它縮短了4行,並且留下了更少的人爲錯誤空間。 – JLRishe

+0

我做了'promisesArray.push(myService.getSomeData($ scope.model.stuff [k] .id));'在for循環中,所以我將值存儲在一個數組中。現在,我想在他們全部跑完之後訪問他們 - 如何? – chiapa