簡體   English   中英

Javascript循環遍歷數組異步

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM