自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

如何使用Promise.race() 和 Promise.any() ?

開(kāi)發(fā) 前端
自1996年發(fā)布以來(lái),JS 一直在穩(wěn)步改進(jìn)。隨著ECMAScript版本的許多改進(jìn),最近的版本是ES2020。JS 的一個(gè)重要更新是Promise,在2015年,它以 ES6 的名義發(fā)布。

 [[357642]]

自1996年發(fā)布以來(lái),JS 一直在穩(wěn)步改進(jìn)。隨著ECMAScript版本的許多改進(jìn),最近的版本是ES2020。JS 的一個(gè)重要更新是Promise,在2015年,它以 ES6 的名義發(fā)布。

什么是 Promise ?

MDN 上對(duì) Promise 的定義:Promise 對(duì)象用于表示一個(gè)異步操作的最終完成 (或失敗)及其結(jié)果值。對(duì)于新手來(lái)說(shuō),這聽(tīng)起來(lái)可能有點(diǎn)太復(fù)雜了。

國(guó)外一位大什么對(duì)Promises的解釋如下:“想象一下你是個(gè)孩子。你老媽向你保證,她下周會(huì)給你買(mǎi)一部新手機(jī)。”

你要到下周才能知道你是否能獲取那部手機(jī)。你老媽要么真的給你買(mǎi)了一個(gè)全新的手機(jī),要么因?yàn)椴婚_(kāi)心就不給你買(mǎi)。

這個(gè)就是一個(gè)Promise。一個(gè)Promise有三個(gè)狀態(tài)。分別是:

  1. Pending:你不知道你是否能得到那部手機(jī)
  2. Fulfilled:老媽高興了,給你買(mǎi)了
  3. Rejected:老娘不開(kāi)森了,不給你買(mǎi)了

這個(gè)是我目前聽(tīng)到,最快能理解 Promise 事例。

如果你還沒(méi)有開(kāi)始學(xué)習(xí) Promise ,建議你這樣做。

Promise包含幾種非常有用的內(nèi)置方法。今天我們主要介紹這兩種方法。

  • Promise.race()-與 ES6 一起發(fā)布
  • Promise.any() -仍處于第4階段的提案中

Promise.race()

Promise.race()方法最初是在 ES6 中引入 Promise 時(shí)發(fā)布的,這個(gè)方法需要一個(gè)iterable作為參數(shù)。

Promise.race(iterable) 方法返回一個(gè) promise,一旦迭代器中的某個(gè)promise解決或拒絕,返回的 promise 就會(huì)解決或拒絕。

與Promise.any()方法不同,Promise.race()方法主要關(guān)注 Promise 是否已解決,而不管其被解決還是被拒絕。

語(yǔ)法

  1. Promise.race(iterable) 

參數(shù)

iterable — 可迭代對(duì)象,類似 Array。iterable 對(duì)象實(shí)現(xiàn)Symbol.iterator方法。

返回值

一個(gè)待定的 Promise 只要給定的迭代中的一個(gè)promise解決或拒絕,就采用第一個(gè)promise的值作為它的值,從而異步地解析或拒絕(一旦堆棧為空)。

注意

因?yàn)閰?shù)接受iterable,所以我們可以傳遞一些值,比如基本值,甚至數(shù)組中的對(duì)象。在這種情況下,race方法將返回傳遞的第一個(gè)非 promise 對(duì)象。這主要是因?yàn)榉椒ǖ男袨槭窃谥悼捎脮r(shí)(當(dāng) promise 滿足時(shí))立即返回值。

此外,如果在iterable中傳遞了已經(jīng)解決的Promise,則Promise.race()方法將解析為該值的第一個(gè)。如果傳遞了一個(gè)空的Iterable,則race方法將永遠(yuǎn)處于待處理狀態(tài)。

事例

  1. const promise1 = new Promise((resolve, reject) => { 
  2.     setTimeout(resolve, 500, 'promise 1 resolved'); 
  3. }); 
  4.  
  5. const promise2 = new Promise((resolve, reject) => { 
  6.     setTimeout(reject, 100, 'promise 2 rejected'); 
  7. }); 
  8.  
  9. const promise3 = new Promise((resolve, reject) => { 
  10.     setTimeout(resolve, 200, 'promise 3 resolved'
  11. }); 
  12.  
  13. (async () => { 
  14.     try { 
  15.         let result = await Promise.race([promise1, promise2, promise3]); 
  16.         console.log(result); 
  17.     } catch (err) { 
  18.         console.error(err); 
  19.     } 
  20. })(); 
  21.   // 輸出- "promise 2 rejected" 
  22.   // 盡管promise1和promise3可以解決,但promise2拒絕的速度比它們快。 
  23.   // 因此Promise.race方法將以promise2拒絕 

真實(shí)用例

現(xiàn)在,你可能想知道,我們?cè)趯?shí)戰(zhàn)中何時(shí) Promise.race() ?來(lái)看看。

在請(qǐng)求數(shù)據(jù)時(shí),顯示加載動(dòng)畫(huà)

使用加載動(dòng)畫(huà)開(kāi)發(fā)中是非常常見(jiàn)。當(dāng)數(shù)據(jù)響應(yīng)時(shí)間較長(zhǎng)時(shí),如果沒(méi)使用加載動(dòng)畫(huà),看起來(lái)就像沒(méi)有響應(yīng)一樣。但有時(shí),響應(yīng)太快了,我們需要加載動(dòng)畫(huà)時(shí),增加一個(gè)非常小延遲時(shí)間,這樣會(huì)讓用戶覺(jué)得我是在經(jīng)常請(qǐng)求過(guò)來(lái)的。要實(shí)現(xiàn)這一點(diǎn),只需使用Promise.race()方法,如下所示。

  1. function getUserInfo(user) { 
  2.   return new Promise((resolve, reject) => { 
  3.     // had it at 1500 to be more true-to-life, but 900 is better for testing 
  4.     setTimeout(() => resolve("user data!"), Math.floor(900*Math.random())); 
  5.   }); 
  6.  
  7. function showUserInfo(user) { 
  8.   return getUserInfo().then(info => { 
  9.     console.log("user info:", info); 
  10.     return true
  11.   }); 
  12.  
  13. function showSpinner() { 
  14.   console.log("please wait..."
  15.  
  16. function timeout(delay, result) { 
  17.   return new Promise(resolve => { 
  18.     setTimeout(() => resolve(result), delay); 
  19.   }); 
  20. Promise.race([showUserInfo(), timeout(300)]).then(displayed => { 
  21.   if (!displayed) showSpinner(); 
  22. }); 

**取消的 Promise **

有些情況下,我們需要取消 Promise,這時(shí)也可以借助 Promise.race() 方法:

  1. function timeout(delay) { 
  2.   let cancel; 
  3.   const wait = new Promise(resolve => { 
  4.     const timer = setTimeout(() => resolve(false), delay); 
  5.     cancel = () => { 
  6.       clearTimeout(timer); 
  7.       resolve(true); 
  8.     }; 
  9.   }); 
  10.   wait.cancel = cancel; 
  11.   return wait; 
  12.  
  13.  
  14. function doWork() { 
  15.   const workFactor = Math.floor(600*Math.random()); 
  16.   const work = timeout(workFactor); 
  17.    
  18.   const result = work.then(canceled => { 
  19.     if (canceled) 
  20.       console.log('Work canceled'); 
  21.     else 
  22.       console.log('Work done in', workFactor, 'ms'); 
  23.     return !canceled; 
  24.   }); 
  25.   result.cancel = work.cancel; 
  26.   return result; 
  27.  
  28. function attemptWork() { 
  29.   const work = doWork(); 
  30.   return Promise.race([work, timeout(300)]) 
  31.     .then(done => { 
  32.       if (!done) 
  33.         work.cancel(); 
  34.       return (done ? 'Work complete!' : 'I gave up'); 
  35.   }); 
  36.  
  37. attemptWork().then(console.log); 

批處理請(qǐng)求,用于長(zhǎng)時(shí)間執(zhí)行

Chris Jensen 有一個(gè)有趣的race()方法用例。他曾使用Promise.race()方法批處理長(zhǎng)時(shí)間運(yùn)行的請(qǐng)求。這樣一來(lái),他們可以保持并行請(qǐng)求的數(shù)量固定。

  1. const _ = require('lodash'
  2.  
  3. async function batchRequests(options) { 
  4.     let query = { offset: 0, limit: options.limit }; 
  5.  
  6.     do { 
  7.         batch = await model.findAll(query); 
  8.         query.offset += options.limit; 
  9.  
  10.         if (batch.length) { 
  11.             const promise = doLongRequestForBatch(batch).then(() => { 
  12.                 // Once complete, pop this promise from our array 
  13.                 // so that we know we can add another batch in its place 
  14.                 _.remove(promises, p => p === promise); 
  15.             }); 
  16.             promises.push(promise); 
  17.  
  18.             // Once we hit our concurrency limit, wait for at least one promise to 
  19.             // resolve before continuing to batch off requests 
  20.             if (promises.length >= options.concurrentBatches) { 
  21.                 await Promise.race(promises); 
  22.             } 
  23.         } 
  24.     } while (batch.length); 
  25.  
  26.     // Wait for remaining batches to finish 
  27.     return Promise.all(promises); 
  28.  
  29. batchRequests({ limit: 100, concurrentBatches: 5 }); 

Promise.any()

Promise.any() 接收一個(gè)Promise可迭代對(duì)象,只要其中的一個(gè) promise 成功,就返回那個(gè)已經(jīng)成功的 promise 。如果可迭代對(duì)象中沒(méi)有一個(gè) promise 成功(即所有的 promises 都失敗/拒絕),就返回一個(gè)失敗的 promise 和AggregateError類型的實(shí)例,它是 Error 的一個(gè)子類,用于把單一的錯(cuò)誤集合在一起。本質(zhì)上,這個(gè)方法和Promise.all()是相反的。

注意!Promise.any() 方法依然是實(shí)驗(yàn)性的,尚未被所有的瀏覽器完全支持。它當(dāng)前處于 TC39 第四階段草案(Stage 4)

語(yǔ)法

  1. Promise.any(iterable); 

參數(shù)

iterable — 個(gè)可迭代的對(duì)象, 例如 Array。

返回值

  • 如果傳入的參數(shù)是一個(gè)空的可迭代對(duì)象,則返回一個(gè) 已失敗(already rejected) 狀態(tài)的 Promise。
  • 如果傳入的參數(shù)不包含任何 promise,則返回一個(gè) **異步完成 (asynchronously resolved)**的 Promise。
  • 其他情況下都會(huì)返回一個(gè)處理中(pending) 的 Promise。只要傳入的迭代對(duì)象中的任何一個(gè) promise 變成成功(resolve)狀態(tài),或者其中的所有的 promises 都失敗,那么返回的 promise 就會(huì) 異步地(當(dāng)調(diào)用棧為空時(shí)) 變成成功/失敗(resolved/reject)狀態(tài)。

說(shuō)明

這個(gè)方法用于返回第一個(gè)成功的 promise 。只要有一個(gè) promise 成功此方法就會(huì)終止,它不會(huì)等待其他的 promise 全部完成。

不像 Promise.all() 會(huì)返回一組完成值那樣(resolved values),我們只能得到一個(gè)成功值(假設(shè)至少有一個(gè) promise 完成)。當(dāng)我們只需要一個(gè) promise 成功,而不關(guān)心是哪一個(gè)成功時(shí)此方法很有用的。

同時(shí), 也不像 Promise.race() 總是返回第一個(gè)結(jié)果值(resolved/reject)那樣,這個(gè)方法返回的是第一個(gè) 成功的 值。這個(gè)方法將會(huì)忽略掉所有被拒絕的 promise,直到第一個(gè) promise 成功。

事例

  1. const promise1 = new Promise((resolve, reject) => { 
  2.   setTimeout(reject, 100, 'promise 1 rejected'); 
  3. }); 
  4.  
  5. const promise2 = new Promise((resolve, reject) => { 
  6.   setTimeout(resolve, 400, 'promise 2 resolved at 400 ms'); 
  7. }); 
  8.  
  9. const promise3 = new Promise((resolve, reject) => { 
  10.   setTimeout(resolve, 700, 'promise 3 resolved at 800 ms'); 
  11. }); 
  12.  
  13. (async () => { 
  14.   try { 
  15.     let value = await Promise.any([promise1, promise2, promise3]); 
  16.     console.log(value); 
  17.   } catch (error) { 
  18.     console.log(error); 
  19.   } 
  20. })(); 
  21.  
  22. //Output - "promise 2 resolved at 400 ms" 

從上面代碼注意到Promise.any()主要關(guān)注解析的值。它會(huì)忽略在100毫秒時(shí)拒絕的promise1,并考慮在400毫秒后解析的promise2的值。

真實(shí)用例

從最快的服務(wù)器檢索資源

假設(shè)訪問(wèn)我們網(wǎng)站的用戶可能來(lái)自全球各地。如果我們的服務(wù)器基于單個(gè)位置,那么響應(yīng)時(shí)間將根據(jù)每個(gè)用戶的位置而不同。但是如果我們有多個(gè)服務(wù)器,可以使用能夠產(chǎn)生最快響應(yīng)的服務(wù)器。在這種情況下,可以使用Promise.any()方法從最快的服務(wù)器接收響應(yīng)。

我是小智,我們下期再見(jiàn)!

作者:Mahdhi Rezvi 譯者:前端小智 來(lái)源: medium

原文:https://blog.bitsrc.io/introduction-to-promise-race-and-promise-any-with-real-life-examples-9d8d1b9f8ec9

本文轉(zhuǎn)載自微信公眾號(hào)「大遷世界」,可以通過(guò)以下二維碼關(guān)注。轉(zhuǎn)載本文請(qǐng)聯(lián)系大遷世界公眾號(hào)。

 

責(zé)任編輯:武曉燕 來(lái)源: 大遷世界
相關(guān)推薦

2021-04-28 08:21:21

Promise.any服務(wù)器場(chǎng)景

2024-05-20 01:10:00

Promise變量

2023-09-15 15:31:23

異步編程Promise

2020-09-18 09:02:20

JavaScript

2023-01-12 11:23:11

Promise異步編程

2021-03-15 08:15:42

ES2021語(yǔ)言開(kāi)發(fā)

2022-09-28 12:23:36

Promise代碼

2023-10-08 10:21:11

JavaScriptAsync

2020-07-29 17:35:08

Promise源碼前端

2021-04-27 08:31:37

Promisereject信息

2021-04-29 08:28:24

架構(gòu)參數(shù)傳遞

2021-09-02 12:07:48

Swift 監(jiān)聽(tīng)系統(tǒng)Promise

2023-10-04 07:25:59

JavaScriptpromises

2021-03-09 07:37:42

技術(shù)Promise測(cè)試

2018-03-13 16:04:45

Promise執(zhí)行順序

2019-12-09 15:20:09

JavascriptPromise前端

2015-07-23 11:59:27

JavascriptPromise

2017-05-11 20:20:59

JavascriptPromiseWeb

2020-08-31 08:11:01

V8 8.5Promise前端

2022-01-21 08:50:15

Promise任務(wù)隊(duì)列前端
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)