[英]Javascript loop through array asynchronous
我正在為在 NodeJS 上運行的游戲制作機器人代碼,這個函數應該做的是循環遍歷向量數組,然后讓機器人轉到每個向量。
然而,它實際上在做的是告訴機器人同時運行到所有的向量,這樣它就會噴出然后運行到數組中的最后一個向量:
function digSchedule() {
var arrayLength = blocksToMine.length;
for (var i = 0; i < blocksToMine.length; i++) {
console.log(i);
scaffoldTo(blocksToMine[i]);
}
...
}
需要運行函數scaffoldTo()
,然后等待機器人執行所述函數,然后為數組中的下一個元素運行它,但我不知道該怎么做。
有幾種方法可以實現這一點。 第一個可能是傳遞帶有“下一個要調用的函數”的回調(可能是scaffoldTo()
)。 您可以使用.bind()
創建具有迭代器索引i
的引用。
或者,您可以設置一個Promise
循環,根據定義,它有一個.then()
方法,該方法在承諾解決后執行。
最后, async
/ await
模式類似於 Promises,但有些人發現它更清晰,似乎正在贏得炒作戰爭: https ://hackernoon.com/6-reasons-why-javascripts-async-await-blows-promises -away-tutorial-c7ec10518dd9 。
回調(解決方案 1)將在任何版本的 JS 中可用。 Promise 通常在庫中可用,並且在 ES6 中具有原生支持。 Async/await 是 ES2017 中的一個提議(?),通常得到很好的支持。
這是 ES2017 異步函數的一個很好的用例。
請嘗試以下方法:
async function digSchedule() {
var arrayLength = blocksToMine.length;
for (var i = 0; i < blocksToMine.length; i++) {
console.log(i);
await scaffoldTo(blocksToMine[i]);
}
...
}
如果 ES2017 是不可能的,那么您最好的選擇是創建一個遞歸函數,該函數只有在解決來自scaffoldTo
的承諾時才會再次調用自己。
這是您可以使用它的另一種方式。 這種方式更側重於回調樣式,盡管它確實假設您可以修改scaffoldTo函數,以及digSchedule所需的參數
function digSchedule(i, callback) {
if(!i){
i = 0;
}
if(i < blocksToMine.length){
scaffoldTo(blocksToMine[i], digSchedule(i++, callback));
}
else{
callback();
}
}
然后在腳手架內部你需要這樣的東西
function scaffoldTo(block, callback){
//do what ever you need to have the bot go to the vector
//after bot goes to vector call callback
callback();
}
為了開始這一切,你只需要像這樣調用 digSchedule :
digSchedule({null or 0}, function(){
console.log("finished visiting vectors");
});
這確實改變了使用 for 循環的模式,但我認為這也是實現目標的一種有趣方式。
我正在為在 NodeJS 上運行的游戲制作一個機器人代碼,這個函數應該做的是循環遍歷一個向量數組,然后讓機器人轉到每個向量。
然而,它實際做的是告訴機器人同時運行到所有向量,這樣它就會消失,然后運行到數組中的最后一個向量:
function digSchedule() {
var arrayLength = blocksToMine.length;
for (var i = 0; i < blocksToMine.length; i++) {
console.log(i);
scaffoldTo(blocksToMine[i]);
}
...
}
函數scaffoldTo()
需要運行,然后等待機器人執行所述函數,然后為數組中的下一個元素運行它,但我不知道如何去做。
您可以使用異步模塊來實現這一點。 或者,您可以嘗試這樣的事情
function forEachAsync(array, fun, cb) {
var index = 0;
if (index == array.length) {
cb(null);
return;
}
var next = function () {
fun(array[index], function(err) {
if (err) {
cb(err);
return;
}
index++;
if (index < array.length) {
setImmediate(next);
return;
}
//We are done
cb(null);
});
};
next();
}
forEachAsync([1,2,3,4,5], function(e, cb) {
console.log(e);
cb();
}, function(err) {
console.log('done');
});
下面是我們如何在 Promise 的幫助下做的事情。
let numbers = new Array(1,3,2,1);
function asyncFunction(number){
return new Promise((resolve,reject)=>{
setTimeout(()=>{
console.log("Number : ",number);
return resolve();
},number*1000);
})
}
let promise = Promise.resolve();
// Here we are using forEach to chain promise one after another.
numbers.forEach(number=>{
promise = promise.then(()=>{
return asyncFunction(number);
});
})
promise.then(()=>{
console.log("Every thing is done!");
})
使用while
循環,您可以更好地控制迭代的行為。
const array = ['item1', 'item2', 'item3', 'item4']
let index = 0;
while (index < array.length) {
await doSomethingAsync(array[index]);
console.log('Done with : ' + index);
// Another function to run before the next item is handled
index++; // Increment index at the end
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.