1

Code without any handling:

  for (i=0; i<dbImgCount; i++){
        (function(i) {
             imgDownload(FolderPath[i].FolderPath, function (next){
                var url = FolderPath[i].FolderPath;
                const img2 = cv.imread(imgDownload.Filename);
                match({url,
                    img1,
                    img2,
                    detector: new cv.ORBDetector(),
                    matchFunc: cv.matchBruteForceHamming,
                });

            })
        })(i);
      }

In the above code, imgDownload is an async function which will download image, match will match features of downloaded image with another image. Need to execute a function after this for-loop.

How to restructure this code, using Promise or async-await, so that each call to asynchronous function is waited for and only after completing the for-loop, flow continues?


Edited the code with async-await:

    FolderPath.forEach(FolderPath => {
        (async function () {
            var filename = await imgDownload(FolderPath.FolderPath);
            var url = FolderPath.FolderPath;
            const img2 = cv.imread(filename);
            imgs = await match({url,
                img1,
                img2,
                detector: new cv.ORBDetector(),
                matchFunc: cv.matchBruteForceHamming,
            });
        })();
    });

    function someFunction(){
       console.log("After forEach");
    }

How to execute someFunction only after forEach?

9
  • 1
    Does imgDownload support promises? If not, start with that Commented Sep 11, 2018 at 13:08
  • "so that I can execute a callback function after this." - well, no, if you want to go with promises you would not take a callback function to call after this, you would instead return a promise for the matches. Commented Sep 11, 2018 at 13:09
  • I used image-downloader npm package, it supports Promise. npmjs.com/package/image-downloader Commented Sep 11, 2018 at 13:11
  • OK. Did you have a look at their example and tried to apply it for your case? Commented Sep 11, 2018 at 13:18
  • Using async/await? what should I do with that? var promise1 = new Promise(function(resolve, reject) { resolve('Success!'); }); promise1.then(function(value) { console.log(value); // expected output: "Success!" }); Use promise like this? Commented Sep 11, 2018 at 13:25

2 Answers 2

3

With your last update, although you have used async-await inside for-loop, but that did't stoped your synchronous flow.

I'm assuming your imgDownload and match functions are returning promise.

Then new Code will be:

(async function () {

    // Next loop won't be executing without completing last.
    for (i = 0; i < FolderPath.length; i++) {

        var filename = await imgDownload(FolderPath[i].FolderPath);
        var url = FolderPath[i].FolderPath;

        const img2 = cv.imread(filename);

        imgs = await match({url,
            img1,
            img2,
            detector: new cv.ORBDetector(),
            matchFunc: cv.matchBruteForceHamming,
        });
    }

    // Now will wait for for-loop to end
    function someFunction(){
       console.log("After forEach");
    }
// End of async-await
})();

Here's a small sample example:

(async function () { 
    for (i=0; i<5; i++) {
        x = await main();
        console.log(x, i);
    }
    console.log("Finally");
})();

// asynchronous main function
function main() {
    return new Promise( (resolve, reject) => {
        setTimeout(()=> { resolve('Done'); }, 5000)
    });
}
Sign up to request clarification or add additional context in comments.

2 Comments

SyntaxError: await is only valid in async function This will be the output.
await is inside async function
0

Thanks everyone for the comments.

   (async function () { 
        for (i = 0; i < FolderPath.length; i++) {
            var filename = await imgDownload(FolderPath[i].FolderPath);
            var url = FolderPath[i].FolderPath;
            const img2 = cv.imread(filename);
            imgs = await match({url,
                img1,
                img2,
                detector: new cv.ORBDetector(),
                matchFunc: cv.matchBruteForceHamming,
            });
        }
        console.log("After forEach");
    })();

This is working - "After forEach" displays only after for loop.


When using forEach as mentioned in the answer above.

(async function () {

   // Next loop won't be executing without completing last.
  FolderPath.forEach(FolderPath => {

    var filename = await imgDownload(FolderPath.FolderPath);
    var url = FolderPath.FolderPath;

    const img2 = cv.imread(filename);

    imgs = await match({url,
        img1,
        img2,
        detector: new cv.ORBDetector(),
        matchFunc: cv.matchBruteForceHamming,
    });
});

// Now will wait for for-loop to end
function someFunction(){
   console.log("After forEach");
}
// End of async-await
})();

Output is - SyntaxError: await is only valid in async function.

I think await keyword won't be in scope of async function, when it comes under forEach, that should be the reason.

2 Comments

Yes, didn't noticed, forEach takes a callback function, which takes it out of scope of async, thus await is used outside async.
You could had just edited my answer with for-loop, as it's the solution for your problem.

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.