使用承诺来控制stream量工作不正常

我试图控制下面代码中的执行stream程,这意味着我希望它是串行的。

我正在读取和更新数据到我的数据库,并且我希望以正确的顺序发生。 下面是我打电话给我的数据库的function,查询function被封装在callback中。

我对承诺相当陌生,所以也许错误可能是我忽略的一些愚蠢的东西。 如果你需要任何问题,请这样做。

function my_function(array, array2) { var array3 = []; return Promise.resolve(true) .then(function() { console.log("1") for(var i=0; i< array.length; i++) { get(array[i], function(results){ console.log("2") array3.push(..); }); } return array3; }).then(function() { console.log("3") for(var i=0; i< array2.length; i+=2) { //... get(array2[i], function(results){ console.log("4") return array3.push(...); }); } return array3; }).then(function(array3) { console.log("5") for(var i=0; i<array3.length; i++) { get(array3[i], function(results){ console.log("6") update(.., function(callb_result){ return; }); }); } }); } 

这就是我正在调用查询的方式。

 function get(array, callback) { db.get(`SELECT .. FROM .. WHERE ..;`, function(error, row) { ... return callback(something); }); } function update(.., callback) { db.run(`UPDATE .. SET ...`); return callback("updated"); //I dont want to return anything } 

什么打印在日志中

 1 3 5 2 4 6 

我在想也许我可能调用查询的方式是asynchronous的,这就搞乱了一切。

您正在使用for循环来运行asynchronous任务并返回由它们修改的数组。 但是因为它们是asynchronous的,所以在完成之前发生。 相反,您可以创build一个承诺数组,其中每个承诺是完成任务后解决的asynchronous任务之一。 要等到每个任务完成,您可以调用Promise.allPromise.all数组,这将返回一个承诺,parsing结果的数组。

首先.then你可以使用Array.prototype.map轻松创build一个promise数组。 数组中的每一项都需要返回一个new Promise ,以get的callback结果解决。

 .then(function() { console.log("1"); const promiseArray = array.map(function(item) { return new Promise(function(resolve) { get(item, function(result) { console.log("2"); resolve(result); }); }); }); return Promise.all(promiseArray); }) 

当你返回Promise.all .then一旦promiseArray中的所有promiseArray都得到满足.then就会执行下一个Promise.all调用。 它将接收结果数组作为函数的第一个参数。 这意味着你可以在那里使用它们。 第二个。然后是类似的第一个,除了你不想打电话get每一个项目。 在这种情况下map不适用,所以for循环只会创build一个promise并将其添加到promise数组中。 在你使用array3来存储你想要更新的结果之前,你可能并不需要这些。 在这种情况下,您可以简单地concat两个数组的结果。

 .then(function(resultsArray) { console.log("3"); const promiseArray2 = []; for (var i = 0; i < array2.length; i += 2) { const promise = new Promise(function(resolve) { get(array2[i], function(results) { console.log("4"); resolve(results); }); }); promiseArray2.push(promise); } // Wait for all promises to be resolved // Then concatenate both arrays of results return Promise.all(promiseArray2).then(function(resultsArray2) { return resultsArray.concat(resultsArray2); }); }) 

这将返回一个用连接数组解决的承诺,因此您将所有结果(从.then调用中)作为数组传递给下一个.then函数。 在第三个也是最后一个.then你只需要在数组的每个元素上调用update 。 你不需要再次打电话get你,因为你已经完成了这个任务,并且你传递了结果。

 .then(function(finalResults) { console.log("5"); for (var i = 0; i < finalResults.length; i++) { console.log("6"); update(finalResults[i], function(result) { console.log(result); }); } }); 

完全可运行的代码get使用超时模拟asynchronous调用)

 function myFunction(array, array2) { return Promise.resolve(true) .then(function() { console.log("1"); const promiseArray = array.map(function(item) { return new Promise(function(resolve) { get(item, function(results) { console.log("2"); resolve(results); }); }); }); return Promise.all(promiseArray); }) .then(function(resultsArray) { console.log("3"); const promiseArray2 = []; for (var i = 0; i < array2.length; i += 2) { const promise = new Promise(function(resolve) { get(array2[i], function(results) { console.log("4"); resolve(results); }); }); promiseArray2.push(promise); } return Promise.all(promiseArray2).then(function(resultsArray2) { return resultsArray.concat(resultsArray2); }); }) .then(function(finalResults) { console.log("5"); for (var i = 0; i < finalResults.length; i++) { console.log("6"); update(finalResults[i]); } }); } function get(item, cb) { // Simply call the callback with the item after 1 second setTimeout(() => cb(item), 1000); } function update(item) { // Log what item is being updated console.log(`Updated ${item}`); } // Test data const array = ["arr1item1", "arr1item2", "arr1item3"]; const array2 = ["arr2item1", "arr2item2", "arr2item3"]; myFunction(array, array2);