Home > Net >  Node Js how to call an asynchronous function that returns a promise
Node Js how to call an asynchronous function that returns a promise

Time:05-04

I have an exercise that includes the following mandatory include.

const Resolver= require('./resolver.js');

Resolver has an asynchronous method called resolveIdFunc that accepts a string "id" and returns a promise which might resolve after a random period of time.

My question is, I have an array of ids ['id1', 'id2', ...]

How do I run these ids with the resolveIdFunc, i.e. how do I call this async function that returns a promise.

I tried

for (let i = 0; i <= ids.length - 1; i  ){
    let promise = new Promise (async (response, reject) => {
      let result = await Resolver.resolveIdFunc(ids[0]);
          if(result){...}
    }
}

but the results are always undefined.

CodePudding user response:

As I understood from the comments of yours, you need to get an array that contains the ids in the order that they have been finished. If it's correct then when you call an asynchronous function with await, the code is blocked in that place until that function returns the result, so if you'll write something like this:

let resultsInOrder = [];
for(let id of ids) {
  let result = await Resolver.resolveIdFunc(ids[0]);
  if(result) {
    resultsInOrder.push(id);
  }
}

the "for(let id of ids)" just takes the id from that array on every iteration.

CodePudding user response:

you use Promise.all

const promises = ids.map(id => TaskRunner.resolveIdFunc(id));
const result = await Promise.all(promises);

If you want to record the order that the results were sent you can do so like this:

const promises = ids.map(async (id,index) => {
      var resolvedValue = await TaskRunner.resolveIdFunc(id);
      return {index,resolvedValue}
});
const result = await Promise.all(promises);

Here's alove example of this in action (mocking out your resolve function)

const TaskRunner = {
   resolveIdFunc: function(id){
      return new Promise(resolve => setTimeout(() => resolve(id), id*100)) 
   }
};


(async function(){
  const ids = [1,2,3];
  const promises = ids.map(async (id,index) => {
        const resolvedValue = await TaskRunner.resolveIdFunc(id);
        return {index,resolvedValue}
  });
  const result = await Promise.all(promises);

  console.log(result);
})()

CodePudding user response:

Usually you just do

for (const id of ids) {
   const result = await resolveIdFun(id);
   if (result) {
     // 
   }
}

or even simpler

const result = await Promise.all(ids.map(resolveIdFun));

If in your example result is undefined, then TaskRunner.resolveIdFunc returned a Promise that actually resolved to undefined. You should step thorugh the code with a debugger to find out why it's returning undefined.

Edit Regarding your comment

let order = 0;
// Kick off all at once and remember order of completion
const promises = ids.map(id =>
  resolveIdFunc(id).then(result => ({ order: order  , result }));

// Wait for all and sort by order, then map back to result
const results = await Promise.all(promises)
  .sort((a, b) => a.order - b.order)
  .map(r => r.result);
  • Related