JS 中實(shí)現(xiàn)一個(gè)串型異步函數(shù)隊(duì)列
背景
在日常業(yè)務(wù)開(kāi)發(fā)中,總會(huì)遇到這種場(chǎng)景,有一串請(qǐng)求,下一個(gè)請(qǐng)求依賴上一個(gè)異步請(qǐng)求的結(jié)果,一般來(lái)說(shuō),我在處理這種需求的時(shí)候使用 async/await
。但是在某些情況(比如面試),可能需要提供更加高級(jí)的解決方案。
通常解法
async/await 串型請(qǐng)求
// 生成異步請(qǐng)求函數(shù) /* @param {boolean} isSuccess 是否成功 @param {number} delay 請(qǐng)求返回時(shí)間 @return {Promise} promise */ function genAsyncTask(isSuccess, delay) { return (params) => { return new Promise((resolve, reject) => { setTimeout(() => { isSuccess ? resolve(params || 'success') : reject('error') }, delay) }) } } // 異步請(qǐng)求 const asyncTask1 = genAsyncTask(true, 1000) const asyncTask2 = genAsyncTask(true, 2000) const asyncTask3 = genAsyncTask(true, 3000) // 通常解法 ;(async()=>{ let result1 = await asyncTask1('a') let result2 = await asyncTask2(result1) await asyncTask3(result2) // ... })()
for...of 解法
不依賴上次結(jié)果,只要求順序執(zhí)行時(shí),注意和Promise.all()
區(qū)別
const asyncTasks = [asyncTask3, asyncTask2, asyncTask1] ;(async()=>{ for(task of asyncTasks){ console.log(await task()) } })() // 輸出:success 3s之后 // 輸出:success 再2s之后 // 輸出:success 再1s之后
需求一
- 實(shí)現(xiàn) queuePromsies 方法
- 入?yún)楫惒秸?qǐng)求函數(shù)數(shù)組
- 上個(gè)結(jié)果作為下個(gè)異步函數(shù)的入?yún)?/li>
reduce 實(shí)現(xiàn)
/* reduce @param {array} promises 異步請(qǐng)求函數(shù)數(shù)組 note: 傳入異步函數(shù),它返回 promise。而不是傳入 promise 對(duì)象。 @initInput (any) initInput 初始參數(shù),作為 reduce 初始值參數(shù) */ function queuePromises(asyncTasks, initInput = 'initInput') { return asyncTasks.reduce( (preAsyncTask, curAsyncTask) => preAsyncTask.then((result) => { return curAsyncTask(result) }), Promise.resolve(initInput) ) } /* 測(cè)試用例 */ ;(async () => { try { let result = await queuePromises([asyncTask1, asyncTask2, asyncTask3]) console.log(result) } catch (error) { console.log('error', error) } })() // 輸出:initInput
需求二
- 實(shí)現(xiàn) chainPromise 函數(shù)
- 不使用 async / await 語(yǔ)法
- 實(shí)現(xiàn)單個(gè) promise 失敗后重新執(zhí)行的配置,即 promise 失敗后允許繼續(xù)嘗試發(fā)送幾次請(qǐng)求,重傳次數(shù)用完則認(rèn)為失敗,進(jìn)入 catch
遞歸實(shí)現(xiàn)
// 遞歸解法 function chainPromise(tasks, { limit } = { limit: 3 }) { const results = [] let tryTimes = 1 let index = 0 function next() { const task = tasks[index] if (task) { return task().then( (result) => { tryTimes = 1 index++ results.push(result) return next() }, (reason) => { if (tryTimes <= limit) { console.log('try!!!', tryTimes) tryTimes++ return next() } else { throw new Error('limit more than 3') } } ) } else { return Promise.resolve(results) } } return next() } chainPromise([asyncTask1, asyncTask2, asyncTask3]), {limit:3}]).then(console.log) // [1000,2000,3000]
到此這篇關(guān)于JS 中實(shí)現(xiàn)一個(gè)串型異步函數(shù)隊(duì)列的文章就介紹到這了,更多相關(guān)JS串型異步函數(shù)隊(duì)列內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
微信小程序 數(shù)據(jù)緩存實(shí)現(xiàn)方法詳解
這篇文章主要介紹了微信小程序 數(shù)據(jù)緩存實(shí)現(xiàn)方法詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-08-08JavaScript如何從listbox里同時(shí)刪除多個(gè)項(xiàng)目
要從列表框同時(shí)刪除多個(gè)項(xiàng)目只能從下向上刪除,這樣就不會(huì)出現(xiàn)索引號(hào)亂變的問(wèn)題了,下面有個(gè)不錯(cuò)的示例,大家可以感受下2013-10-10JS前端實(shí)現(xiàn)留言板功能的方法總結(jié)
留言板的主要使用場(chǎng)景是為用戶提供一個(gè)在網(wǎng)站或應(yīng)用上留言的平臺(tái),本文主要為大家介紹了四個(gè)常見(jiàn)的前端實(shí)現(xiàn)留言板功能的方法,希望對(duì)大家有所幫助2023-11-11php利用curl獲取遠(yuǎn)程圖片實(shí)現(xiàn)方法
這篇文章主要介紹了php利用curl獲取遠(yuǎn)程圖片實(shí)現(xiàn)方法,curl要求php環(huán)境支持,需要的朋友可以參考下2015-10-10js打開(kāi)windows上的可執(zhí)行文件示例
這篇文章主要介紹了js如何打開(kāi)windows上的可執(zhí)行文件,需要的朋友可以參考下2014-05-05javascript 實(shí)現(xiàn)的多瀏覽器支持的貪吃蛇webgame
兼容FF IE的javascript版貪吃蛇游戲,非常厲害的高手。2008-01-01js給dropdownlist添加選項(xiàng)的小例子
js給dropdownlist添加選項(xiàng)的小例子,需要的朋友可以參考一下2013-03-03