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?

NAVIN
  • 3,193
  • 4
  • 19
  • 32
George T Kurian
  • 183
  • 2
  • 12
  • 1
    Does `imgDownload` support promises? If not, [start with that](https://stackoverflow.com/q/22519784/1048572) – Bergi Sep 11 '18 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. – Bergi Sep 11 '18 at 13:09
  • I used image-downloader npm package, it supports Promise. https://www.npmjs.com/package/image-downloader – George T Kurian Sep 11 '18 at 13:11
  • OK. Did you have a look at [their example](https://www.npmjs.com/package/image-downloader#usage-with-asyncawait) and tried to apply it for your case? – Bergi Sep 11 '18 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? – George T Kurian Sep 11 '18 at 13:25
  • No, you should not use `new Promise`. You should change your deprecated `imgDownload` call to one that returns a promise, so that you can use that promise object. – Bergi Sep 11 '18 at 13:35
  • Do you want the downloads to run concurrently or sequentially? – Bergi Sep 11 '18 at 13:36
  • what is the problem with using async/await here? – Jacob Sep 11 '18 at 17:40
  • Hey, my requirement is: first `imgDownload` will run and download an image, then, `match` will match the downloaded image with another one. After the for loop, I want to execute another function. Help me to restructure this in asynchronous way of doing things! – George T Kurian Sep 12 '18 at 04:39

2 Answers2

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)
    });
}
NAVIN
  • 3,193
  • 4
  • 19
  • 32
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.

George T Kurian
  • 183
  • 2
  • 12
  • 1
    Yes, didn't noticed, `forEach` takes a `callback` function, which takes it out of scope of `async`, thus `await` is used outside `async`. – NAVIN Sep 12 '18 at 10:41
  • 1
    You could had just edited my answer with `for-loop`, as it's the solution for your problem. – NAVIN Sep 12 '18 at 10:44