user7025244
user7025244

Reputation:

Trouble with await/async

var images = ['image', 'image2', 'image3'];

async function proccess_images(images) {
  for (const image of images) {
    await postprocess(image)
  }
  console.log('done'); //this prints out before for loop is finished
}

async function postprocess(image) {
    await process(function(data) {
      console.log(data);
    }, image)
};


function process(callback, image) {
  3rdpartylibrary.process(image, (err, data) => {
      if(err) {
        console.error(err);
      } else {
        console.log('not done')
        callback(data);
      }
    })
  }

proccess_images(images)

I'm having trouble getting an async/await function working with my code that does some image processing using a 3rd party library. I'm trying to get each image to finish processing before moving onto the next image, but currently all three start processing immediately without waiting. It seems like the 3rd party library is starting its process which makes the async/await function think its done, but how do I make sure the next image isn't processed until AFTER 3rdpartylibrary.process has finished processing the data? I've also tried putting

await new Promise ((resolve, reject) =>

In front of the 3rdpartylibrary function which stops them all from processing at the same time, but it causes the for loop to exit after processing the first image correctly. Any ideas as to what I'm doing wrong?

Upvotes: 2

Views: 97

Answers (3)

Rico Kahler
Rico Kahler

Reputation: 19202

You want to wrap the 3rdpartylibrary in a promise. What you want to do is convert the callback style to a promise by wrapping it. This is a good article to refer to. Try this:

var images = ['image1', 'image2', 'image3'];

// mock thirdPartyLibrary
const thirdPartyLibrary = {
  process: (image, callback) => {
    console.log(`processing image ${image}`);
    setTimeout(() => {
      const noError = undefined;
      callback(noError, `finished procesing image ${image}`);
    }, 1000);
  }
}

async function proccess_images(images) {
  console.log('start');
  for (const image of images) {
    console.log(`before processing image ${image}`);
    await process(image);
    console.log(`after processing image ${image}`);
  }
  console.log('done');
}


function process(image) {
  // wrap thirdPartyLibrary in promise
  return new Promise((resolve, reject) => {
    thirdPartyLibrary.process(image, (err, data) => {
      if (err) {
        reject(err);
      } else {
        resolve(data);
      }
    })
  })
}

proccess_images(images)

Upvotes: 0

Neil Lunn
Neil Lunn

Reputation: 151072

Change the process function definition to wrap a Promise:

function process(image) { 
  return new Promise((resolve,reject) => {
    3rdpartylibrary.process(image, (err, data) => { 
      if (err) reject(err);
      resolve(data);
   })
 })
}

The key point being to remove any callback references, since now it returns a Promise so you can await it.

Upvotes: 1

David784
David784

Reputation: 7464

Your problem appears to be that your first function isn't returning a promise. await requires a promise to work correctly. Something like this should work:

async function postprocess(image) {
    var output = await process(image);
    console.log(output);
};


function process(image) {
 return new Promise((resolve, reject) => {
   3rdpartylibrary.process(image, (err, data) => {
      if(err) {
        console.error(err);
        reject(err);
      } else {
        console.log('not done')
        resolve(data);
      }
   })
 });
}

Upvotes: 1

Related Questions