使用承诺来控制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.all
和Promise.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);