最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Promise.all Replacement? - Stack Overflow

programmeradmin1浏览0评论

Is there any way where I can call multiple async functions in Javascript, but get response of the call as soon as one completes, unlike Promise.all that waits for all async calls to complete? What I want is, run async calls in parallel, and get response of a respective call as soon as it gets completed while other calls are still running and then update the react state.

I am already using Promise.all for multiple async calls, but it gives responses when all calls are finished.

Is there any way where I can call multiple async functions in Javascript, but get response of the call as soon as one completes, unlike Promise.all that waits for all async calls to complete? What I want is, run async calls in parallel, and get response of a respective call as soon as it gets completed while other calls are still running and then update the react state.

I am already using Promise.all for multiple async calls, but it gives responses when all calls are finished.

Share Improve this question asked Oct 10, 2019 at 5:40 Syed SaeedulHassan AliSyed SaeedulHassan Ali 5941 gold badge7 silver badges21 bronze badges 4
  • 2 Do you still need the behavior of Promise.all() in addition, or no? – Patrick Roberts Commented Oct 10, 2019 at 5:43
  • I think you are looking for Promise.race. To better understand Promise.race see this – Sufian Saory Commented Oct 10, 2019 at 5:56
  • 2 What you describe is just adding the same callback to all your Promises, is it really just what you want? – Kaiido Commented Oct 10, 2019 at 6:03
  • I want to call async functions, and I need response of every function. But with promise.all, I get all the responses when all calls are successfully completed. What I want is that, calls go asynchronously and I keep getting response as soon as each respective call is completed – Syed SaeedulHassan Ali Commented Oct 10, 2019 at 9:43
Add a comment  | 

4 Answers 4

Reset to default 5

You can just iterate over an array of promises and change the state on each promise resolution:

let state = null;

const p1 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve({p1: 1});
  }, 2000);
});
const p2 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve({p2: 2});
  }, 1000);
});
const p3 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve({p3: 3});
  }, 3000);
});

// Iterate promises
[p1, p2, p3].forEach(p => {
  p.then(res => {
    state = Object.assign({}, state, res);
    console.log(state);
  });
});

console.log(state);

You could create your own Promise method for this task:

if (!Promise.each) {
  Promise.each = function(promises, callback, error) {
    if (promises && Array.isArray(promises)) {
      promises.forEach(p => {
        p.then(res => {
          callback(res);
        }, err => {
          if (error) {
              error(err);
          } else {
              console.log(err);
          }          
        });
      });
    }
  }
}

// Usage
Promise.each([p1, p2, p3], updateState);

In your question the phrase "than update ... state" is the key. You plan to update the state in such a way that as soon as one promise "completed" the corresponding state is updated. You have been trying something like this

async function f1(){ await Promise.resolve(); }
async funciton f2(){ await Promise.resolve(); }
async function fn(){ await Promise.resolve(); }

async function drvAsync(){
  const [r1, r2, rn] = await Promise.all([f1(), f2(), fn()]);
  u1(r1);
  u2(r2);
  un(rn);
}

where f[n] is an async business function, u[n] is a method to deal with the result from it. This schema is not acceptable in your scenario. Perhaps fn completes faster than others and you want to update N-th state earlier.

My recommendation is use no synchronization primitives at all. Instead you should deal with the results separately.

function drv(){
  f1().then((r1)=>u1(r1)).catch((e)=>er(e));
  f2().then((r2)=>u2(r2)).catch((e)=>er(e));
  fn().then((rn)=>un(rn)).catch((e)=>er(e));;  
}

This schema will call each update (u[n]) method without waiting results from others.

This is what Promise.race is for:

The Promise.race() method returns a promise that fulfills or rejects as soon as one of the promises in an iterable fulfills or rejects, with the value or reason from that promise.

For instance:

function sleep(ms) {
  return new Promise((resolve) => setTimeout(resolve, ms));
}

async function main() {
  const promises = [
    sleep(1000).then(() => "world"),
    sleep(100).then(() => "hello"),
  ];
  const promisesWithIndices = promises.map((p, index) =>
    p.then((result) => ({result, index}))
  );
  while (promisesWithIndices.length > 0) {
    const {result, index} = await Promise.race(promisesWithIndices);
    console.log("%s -> %s", index, result);
    promisesWithIndices.splice(index, 1);
  }
}

main();  // prints "1 -> hello"; then prints "0 -> world" after a while

As long as you don't use async/await you can do the calls in parallel. Note that browsers have connection limit for network requests so if you execute for example 100 calls it will not be parallel but rather be queued.

You need a callback to execute when the promise resolved. If this callback is the same for all functions than just loop all calls, create the promise and resolve with the same function.

function resolved(data) {
    // ...
}

const promise1 = new Promise(function(resolve, reject) {
    resolve('Success!');
}).then(resolved);

const promise2 = new Promise(function(resolve, reject) {
    resolve('Success!');
}).then(resolved);
发布评论

评论列表(0)

  1. 暂无评论