JavaScript手寫異步加法asyncAdd方法詳解
前言
在掘金上發(fā)現(xiàn)一道既簡單但個人覺得還挺有意思的一道題,題目如下:
// 異步加法 function asyncAdd(a,b,cb){ setTimeout(() => { cb(null, a + b) }, Math.random() * 1000) } async function total(){ const res1 = await sum(1,2,3,4,5,6,4) const res2 = await sum(1,2,3,4,5,6,4) return [res1, res2] } total() // 實現(xiàn)下 sum 函數(shù)。注意不能使用加法,在 sum 中借助 asyncAdd 完成加法。盡可能的優(yōu)化這個方法的時間。 function sum(){ }
你可以直接嘗試實現(xiàn)下,考察下自己的思維和 JavaScript
基礎(chǔ)知識的聯(lián)系如何,大佬請繞行!
估計大多數(shù)人第一眼看下都不知道這題目到底要干啥(我不說就沒人知道我也是),但是在看第二遍的時候估計就差不多明白具體是要考察什么內(nèi)容了,下面就一起來分析分析吧?。?!
分析 asyncAdd
這里先放置最終結(jié)論:
- 只能修改
sum
部分的內(nèi)容,sum
可接收任意長度的參數(shù) sum
中只能通過asyncAdd
實現(xiàn)加法計算sum
中需要處理異步邏輯,需要使用Promise
- 需要優(yōu)化
sum
方法的計算時間
下面是分別通過對代碼的不同部分進(jìn)行分析,獲取到的相關(guān)的信息。
直觀的基本要求
// 實現(xiàn)下 sum 函數(shù)。注意不能使用加法,在 sum 中借助 asyncAdd 完成加法。盡可能的優(yōu)化這個方法的時間。 function sum(){ }
最直觀的方式就是通過上述的文字描述部分,可以很容易知道題目具體要求:
- 實現(xiàn)
sum
函數(shù),即只能修改sum
部分的內(nèi)容 - 不能直接使用加法(+),通過
asyncAdd
實現(xiàn)加法 - 優(yōu)化
sum
方法的計算時間
隱藏的考察點 — setTimeout & cb
// 異步加法 function asyncAdd(a, b, cb){ setTimeout(() => { cb(null, a + b) }, Math.random() * 1000) }
從上述內(nèi)容來看,最明顯的就是 setTimeout
和 cb
了,其實這不難理解因為在 asyncAdd
中使用了 setTimeout
只能通過回調(diào)函數(shù) cb
將本次計算結(jié)果返回出去,那其中的第一個參數(shù) null
代表什么呢?
其實可以認(rèn)為它是一個錯誤信息對象,如果你比較了解 node
的話,就會知道在 node
中的異步處理的回調(diào)函數(shù)通常第一個參數(shù)就是錯誤對象,用于傳遞給外部在發(fā)生錯誤時自定義后續(xù)執(zhí)行邏輯等。
一句話: cb
函數(shù)會接收 錯誤對象 和 計算結(jié)果 作為參數(shù)傳遞給外部。
隱藏的考察點 — async & await
async function total(){ const res1 = await sum(1,2,3,4,5,6,4) const res2 = await sum(1,2,3,4,5,6,4) return [res1, res2] }
從上述的這部分來看,sum
方法的 返回值 肯定是一個 promise
類型的,因為最前面明顯的使用了 await sum(...)
的形式。
另外 total
函數(shù)返回值也必然是一個 promise
類型,因為整個 total
函數(shù)被定義為了一個 async
異步函數(shù),可點擊此處查看詳細(xì)內(nèi)容。
一句話:sum
需要返回 promise
類型的值,即 sum
一定會使用到 promise
,并且從 sum(1,2,3,4,5,6,4)
可知 sum
可接收任意長度的參數(shù)。
實現(xiàn) asyncAdd
具體實現(xiàn)
實現(xiàn)思路如下:
- 考慮到外部參數(shù)長度不固定,使用剩余運算符接收所有傳入的參數(shù)
- 考慮到
asyncAdd
中的異步操作,將其封裝為Promise
的實現(xiàn),即caculate
函數(shù) - 考慮到
asyncAdd
實際只能一次接收兩個數(shù)字進(jìn)行計算,使用循環(huán)的形式將多個參數(shù)分別傳入 - 考慮到通過循環(huán)處理異步操作的順序問題,使用
async/await
來保證正確的執(zhí)行順序,且async
函數(shù)的返回值正好符合sum
是Promise
類型的要求
具體代碼如下:
// 通過 ES6 的剩余運算符(...) 接收外部傳入長度不固定的參數(shù) async function sum(...nums: number[]) { // 封裝 Promise function caculate(num1: number, num2: number) { return new Promise((resolve, reject) => { // 調(diào)用 asyncAdd 實現(xiàn)加法 asyncAdd(num1, num2, (err: any, rs: number) => { // 處理錯誤邏輯 if (err) { reject(err); return; } // 向外部傳遞對應(yīng)的計算結(jié)果 resolve(rs); }); }) } let res: any = 0; // 通過遍歷將參數(shù)一個個進(jìn)行計算 for (const n of nums) { // 為了避免異步執(zhí)行順序問題,使用 await 等待執(zhí)行結(jié)果 res = await caculate(res, n); } return res; }
進(jìn)行優(yōu)化
抽離內(nèi)層函數(shù)
caculate
函數(shù)可抽離到sum
函數(shù)外層asyncAdd
函數(shù)的回調(diào)函數(shù)沒必要抽離,因為它依賴的參數(shù)和外部方法太多
function caculate(num1: number, num2: number) { return new Promise((resolve, reject) => { asyncAdd(num1, num2, (err: any, rs: number) => { if (err) { reject(err); return; } resolve(rs); }); }) } async function sum(...nums: number[]) { let res: any = 0; for (const n of nums) { res = await caculate(res, n); } return res; }
緩存計算結(jié)果
其實你仔細(xì)觀察 total
方法,其中 sum
調(diào)用了兩次,而且參數(shù)還是一模一樣的,目的就是提示你在第二次計算相同內(nèi)容時結(jié)果直接 從緩存中獲取,而不是在通過異步計算。
async function total(){ const res1 = await sum(1,2,3,4,5,6,4) const res2 = await sum(1,2,3,4,5,6,4) return [res1, res2] }
以下只是一個簡單的緩存方案的實現(xiàn),不必過于糾結(jié),具體實現(xiàn)如下:
const cash: any = {}; function isUndefined(target: any) { return target === void 0; } async function sum(...nums: number[]) { let res: any = 0; const key = nums.join('+'); if (!isUndefined(cash[key])) return cash[key]; for (const n of nums) { res = await caculate(res, n); } cash[key] = res; return res; } function caculate(num1: number, num2: number) { return new Promise((resolve, reject) => { asyncAdd(num1, num2, (err: any, rs: number) => { if (err) { reject(err); return; } resolve(rs); }); }) }
以上就是JavaScript手寫異步加法asyncAdd方法詳解的詳細(xì)內(nèi)容,更多關(guān)于JavaScript異步加法asyncAdd的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
fs-extra實現(xiàn)yarn?create?tlist創(chuàng)建示例詳解
這篇文章主要為大家介紹了fs-extra實現(xiàn)yarn?create?tlist創(chuàng)建示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-01-01微信小程序之獲取當(dāng)前位置經(jīng)緯度以及地圖顯示詳解
最近剛開始接觸微信小程序,在弄懂其結(jié)構(gòu)以及相關(guān)接口之后,準(zhǔn)備著手實現(xiàn)一個小程序,功能包括--獲取用戶當(dāng)前位置的經(jīng)緯度,在地圖上查看位置,通過地圖獲取不同位置的經(jīng)緯度。2017-05-05next.js源碼解析getStaticProps?getStaticPaths使用場景
這篇文章主要為大家介紹了next.js源碼解析getStaticProps?getStaticPaths使用場景,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-08-08