当前位置:网站首页>How to use promise Race() and promise any() ?

How to use promise Race() and promise any() ?

2022-06-25 00:15:00 Front end Xiaozhi

author :Mahdhi Rezvi
translator : The front end little wisdom
source : medium

Have dreams , There are dry goods , WeChat search 【 The big move the world 】 Pay attention to this dish washing wisdom who is still washing dishes in the early morning .

this paper GitHub https://github.com/qq449245884/xiaozhi Included , There is a complete interview site for a large factory 、 Materials and my series .

since 1996 Since its release ,JS Has been steadily improving . With ECMAScript Many improvements to the version , The latest version is ES2020.JS An important update of is Promise, stay 2015 year , It uses ES6 In the name of .

What is? Promise ?

MDN Yes Promise The definition of :Promise Object is used to represent the final completion of an asynchronous operation ( Or failure ) And its result value . For starters , It may sound a little too complicated .

What's wrong with a foreign person Promises Is explained as follows :“ Imagine you're a child . Your mom promised you , She will buy you a new mobile phone next week .”

You don't know if you can get that phone next week . Your mom either actually bought you a brand new cell phone , Or I won't buy you because I'm not happy .

This is a Promise. One Promise There are three states . Namely :

  1. Pending: You don't know if you can get that phone
  2. Fulfilled: Mom is happy , I bought you
  3. Rejected: I don't care anymore , I won't buy you

This is what I've heard so far , The quickest way to understand Promise Example .

If you haven't started learning yet Promise , I suggest you do this .

Promise There are several very useful built-in methods . Today we mainly introduce these two methods .

  • Promise.race()- And ES6 Release together
  • Promise.any() - Still in the first place 4 In the stage proposal

Promise.race()

Promise.race() The method was originally used in ES6 Introduction in Promise When it was released , This method needs a iterable As a parameter .

Promise.race(iterable) Method returns a promise, Once one of the iterators promise To settle or refuse , Back to promise Will solve or refuse .

And Promise.any() The method is different ,Promise.race() Methods focus on Promise Whether it has been solved , Whether it's solved or rejected .

grammar

Promise.race(iterable)

Parameters

iterable — Iteratable object , similar Array. iterable Object implementation Symbol.iterator Method .

Return value

One Pending Promise As long as one of the given iterations promise To settle or refuse , Take the first one promise As its value , thus asynchronous To resolve or reject ( Once the stack is empty ).

Be careful

Because parameters accept iterable, So we can pass some values , For example, the basic value , Even objects in arrays . under these circumstances ,race Method will return the first non passed promise object . This is mainly because the behavior of the method is when the value is available ( When promise When satisfied ) Immediate return value .

Besides , If in iterable It passed on the solved Promise, be Promise.race() Method resolves to the first... Of the value . If an empty Iterable, be race Method will always be in a pending state .

Example

const promise1 = new Promise((resolve, reject) => {
    setTimeout(resolve, 500, 'promise 1 resolved');
});

const promise2 = new Promise((resolve, reject) => {
    setTimeout(reject, 100, 'promise 2 rejected');
});

const promise3 = new Promise((resolve, reject) => {
    setTimeout(resolve, 200, 'promise 3 resolved')
});

(async () => {
    try {
        let result = await Promise.race([promise1, promise2, promise3]);
        console.log(result);
    } catch (err) {
        console.error(err);
    }
})();
  //  Output - "promise 2 rejected"
  //  Even though promise1 and promise3 Can solve , but promise2 Rejection is faster than they are .
  //  therefore Promise.race Method will promise2 Refuse 

Real use cases

Now? , You may want to know , When are we going to Promise.race() ? Let's see .

When requesting data , Display load animation

It is very common to use load animation development . When the data response time is long , If you don't use load animation , It looks like there's no response . But sometimes , The response was too fast , When we need to load animation , Add a very small delay time , This will make users feel that I am frequently asking for it . To achieve this , Just use Promise.race() Method , As shown below .


function getUserInfo(user) {
  return new Promise((resolve, reject) => {
    // had it at 1500 to be more true-to-life, but 900 is better for testing
    setTimeout(() => resolve("user data!"), Math.floor(900*Math.random()));
  });
}

function showUserInfo(user) {
  return getUserInfo().then(info => {
    console.log("user info:", info);
    return true;
  });
}

function showSpinner() {
  console.log("please wait...")
}

function timeout(delay, result) {
  return new Promise(resolve => {
    setTimeout(() => resolve(result), delay);
  });
}
Promise.race([showUserInfo(), timeout(300)]).then(displayed => {
  if (!displayed) showSpinner();
});

Cancelled Promise

In some cases , We need to cancel Promise, You can also use Promise.race() Method :

function timeout(delay) {
  let cancel;
  const wait = new Promise(resolve => {
    const timer = setTimeout(() => resolve(false), delay);
    cancel = () => {
      clearTimeout(timer);
      resolve(true);
    };
  });
  wait.cancel = cancel;
  return wait;
}


function doWork() {
  const workFactor = Math.floor(600*Math.random());
  const work = timeout(workFactor);
  
  const result = work.then(canceled => {
    if (canceled)
      console.log('Work canceled');
    else
      console.log('Work done in', workFactor, 'ms');
    return !canceled;
  });
  result.cancel = work.cancel;
  return result;
}

function attemptWork() {
  const work = doWork();
  return Promise.race([work, timeout(300)])
    .then(done => {
      if (!done)
        work.cancel();
      return (done ? 'Work complete!' : 'I gave up');
  });
}

attemptWork().then(console.log);

Batch request , For long-term execution

Chris Jensen There's an interesting one race() Method use cases . He used Promise.race() Method to batch long running requests . thus , They can keep the number of parallel requests fixed .

const _ = require('lodash')

async function batchRequests(options) {
    let query = { offset: 0, limit: options.limit };

    do {
        batch = await model.findAll(query);
        query.offset += options.limit;

        if (batch.length) {
            const promise = doLongRequestForBatch(batch).then(() => {
                // Once complete, pop this promise from our array
                // so that we know we can add another batch in its place
                _.remove(promises, p => p === promise);
            });
            promises.push(promise);

            // Once we hit our concurrency limit, wait for at least one promise to
            // resolve before continuing to batch off requests
            if (promises.length >= options.concurrentBatches) {
                await Promise.race(promises);
            }
        }
    } while (batch.length);

    // Wait for remaining batches to finish
    return Promise.all(promises);
}

batchRequests({ limit: 100, concurrentBatches: 5 });

Promise.any()

Promise.any() Receive one Promise Iteratable object , Just one of them promise success , Just go back to the successful one promise . If there is not one of the iteratable objects promise success ( That all the promises All failed / Refuse ), Just return a failed promise and AggregateError Instance of type , It is Error A subclass of , Used to group single errors together . Essentially , This method and Promise.all() It's the opposite .

Be careful ! Promise.any() The method is still experimental , Not fully supported by all browsers . It is currently in TC39 The fourth stage draft (Stage 4)

grammar

Promise.any(iterable);

Parameters

iterable — An iteratable object , for example Array.

Return value

  • If the parameter passed in is an empty iteratable object , Returns a Failed (already rejected) State of Promise.
  • If the parameter passed in does not contain any promise, Returns a Asynchronous completion (asynchronously resolved) Of Promise.
  • In other cases, it will return a In processing (pending) Of Promise. As long as any one of the iteration objects passed in promise Become successful (resolve) state , Or all of it promises All failed , So back promise will Asynchronously ( When the call stack is empty ) Become successful / Failure (resolved/reject) state .

explain

This method is used to return the first successful promise . As long as there is one promise If successful, the method will terminate , It won't wait for anything else promise Complete .

Unlike Promise.all() It will return a set of completion values (resolved values), We can only get one success value ( Suppose there is at least one promise complete ). When we just need one promise success , It's useful when you don't care which one is successful .

meanwhile , It's not like Promise.race() Always return the first result value (resolved/reject) like that , This method returns the first The success of value . This method will ignore all rejected promise, Until the first one promise success .

Example

const promise1 = new Promise((resolve, reject) => {
  setTimeout(reject, 100, 'promise 1 rejected');
});

const promise2 = new Promise((resolve, reject) => {
  setTimeout(resolve, 400, 'promise 2 resolved at 400 ms');
});

const promise3 = new Promise((resolve, reject) => {
  setTimeout(resolve, 700, 'promise 3 resolved at 800 ms');
});

(async () => {
  try {
    let value = await Promise.any([promise1, promise2, promise3]);
    console.log(value);
  } catch (error) {
    console.log(error);
  }
})();

//Output - "promise 2 resolved at 400 ms"

Notice from the code above Promise.any() The main concern is the parsed values . It ignores the fact that 100 Rejected in milliseconds promise1, And consider in 400 Resolved in milliseconds promise2 Value .

Real use cases

Retrieve resources from the fastest server

Suppose the users visiting our website may come from all over the world . If our server is based on a single location , The response time will vary depending on the location of each user . But if we have multiple servers , You can use the server that produces the fastest response . under these circumstances , have access to Promise.any() Method to receive the response from the fastest server .

This is Xiaozhi , See you next time !


Possible after code deployment BUG There's no way to know in real time , In order to solve these problems afterwards BUG, It took a lot of time log debugging , This way, I'd like to recommend an easy-to-use one for you BUG Monitoring tools Fundebug.

original text :https://blog.bitsrc.io/introd...

communication

Have dreams , There are dry goods , WeChat search 【 The big move the world 】 Pay attention to this dish washing wisdom who is still washing dishes in the early morning .

this paper GitHub https://github.com/qq44924588... Included , There is a complete interview site for a large factory 、 Materials and my series .

原网站

版权声明
本文为[Front end Xiaozhi]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/02/202202210855489531.html

随机推荐