4

I'm making a bot code for a game running on NodeJS and what this function is supposed to do is to loop through an array of vectors and then make the bot go to each vector.

However, what it's actually doing is telling the bot to run to all the vectors at the same time so it spazzes out and then runs to the last vector in the array:

function digSchedule() {
    var arrayLength = blocksToMine.length;
    for (var i = 0; i < blocksToMine.length; i++) {
        console.log(i);
        scaffoldTo(blocksToMine[i]);
    }
    ...
}

The function scaffoldTo() needs to be ran and then wait for the bot to do said function then run it for the next element in the array, but I can't figure out how to do it.

5
  • Hi D, welcome to SO! Well formatted question with sample code - love it :) Commented Jul 7, 2017 at 22:16
  • 1
    Read up on async Promise Commented Jul 7, 2017 at 22:17
  • Forgot to mention I'm running this on nodeJS it won't let me edit the OP idk Commented Jul 7, 2017 at 22:18
  • I'd assume that scaffoldTo() is async? How is it implemented? How can the loop determine when the function has "finished"? Commented Jul 7, 2017 at 22:21
  • @ScottStensland - as opposed to the synchronous Promise? :p Commented Jul 7, 2017 at 23:04

5 Answers 5

1

There's several ways to achieve this. The first is probably to pass a callback with the "next function to be called" (probably scaffoldTo()). You can use .bind() to create a reference with the iterator index i.

Alternatively, you could set up a loop of Promises, which by definition have a .then() method which executes once the promise is resolved.

Finally, the async/await pattern is similar to Promises, but some find it clearer and it seems to be winning the Hype Wars: https://hackernoon.com/6-reasons-why-javascripts-async-await-blows-promises-away-tutorial-c7ec10518dd9.

Callbacks (solution 1) will be available in any version of JS. Promises generally available with a library and have native support in ES6. Async/await is a proposal (?) in ES2017 and is generally well supported.

Sign up to request clarification or add additional context in comments.

1 Comment

Can you edit the post to include that I'm using NodeJS? I can't edit it after you have.
0

Here's another way that you could play with this. This way focuses more on the callback style, although it does assume that you can modify the scaffoldTo function, as well as the parameters required for digSchedule

function digSchedule(i, callback) {
   if(!i){
      i = 0;
   }
   if(i < blocksToMine.length){
      scaffoldTo(blocksToMine[i], digSchedule(i++, callback));
   }
   else{
     callback();
   }
}

Then inside of scaffoldTo you would need something like this

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

In order to start it all you would just need to call digSchedule with something like this:

digSchedule({null or 0}, function(){
   console.log("finished visiting vectors");
});

This does change the pattern from using a for loop like you have, but I think its a fun way to accomplish the goal as well.

Comments

0

That is a good use case to the async functions of ES2017.

Please, try the following:

async function digSchedule() {
    var arrayLength = blocksToMine.length;
    for (var i = 0; i < blocksToMine.length; i++) {
        console.log(i);
        await scaffoldTo(blocksToMine[i]);
    }
    ...
}

If ES2017 is out of the question, your best choice would be to make a recursive function that only calls itself again when the promise from scaffoldTo is resolved.

4 Comments

I'm on NodeJS and I get this error: SyntaxError: Unexpected token function
You'll need Node 7.6.0 or newer.
And recursion isn't necessary; async/await is just syntactic sugar around Promises. You could use either continuation passing callbacks or an Array of Promises for the result.
0

You may use async module to achieve this. Alternatively, you may try something like this

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');
});

Comments

0

Here is how we do with the help of promises.

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!");
})

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.