首頁 >web前端 >js教程 >JavaScript介紹之手寫非同步加法asyncAdd方法

JavaScript介紹之手寫非同步加法asyncAdd方法

WBOY
WBOY轉載
2022-08-26 14:04:132593瀏覽

本篇文章為大家帶來了關於javascript的相關知識,其中主要為大家介紹了JavaScript手寫異步加法asyncAdd方法詳解,有需要的朋友可以藉鑑參考下,下面一起來看一下,希望對大家有幫助。

JavaScript介紹之手寫非同步加法asyncAdd方法

【相關推薦:javascript影片教學web前端

##前言

在掘金上發現一道既簡單但個人覺得還挺有趣的一道題,題目如下:

// 异步加法
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()
// 实现下 sum 函数。注意不能使用加法,在 sum 中借助 asyncAdd 完成加法。尽可能的优化这个方法的时间。
function sum(){
}

你可以直接嘗試實現下,考察下自己的思維和

JavaScript 基礎知識的連結如何,大佬請繞行!

估計大多數人第一眼看下都不知道這題目到底要幹啥(我不說就沒人知道我也是),但是在看第二遍的時候估計就差不多明白具體是要考察什麼內容了,下面就一起來分析分析吧! ! !

分析asyncAdd

這裡先放置最終結論:

    #只能修改
  • sum 部分的內容,sum可接收任意長度的參數
  • sum 中只能透過asyncAdd 實作加法計算
  • ##sum
  • 中需要處理非同步邏輯,需要使用Promise需要最佳化
  • sum
  • 方法的計算時間
  • 以下是分別透過對程式碼的不同部分進行分析,獲取到的相關的資訊。

直覺的基本要求

// 实现下 sum 函数。注意不能使用加法,在 sum 中借助 asyncAdd 完成加法。尽可能的优化这个方法的时间。 
function sum(){ }

最直觀的方式就是透過上述的文字描述部分,可以很容易知道題目具體要求:

實作
    sum
  • 函數,也就是只能修改sum 部分的內容不能直接使用加法(),透過
  • asyncAdd
  • 實作加法#優化
  • sum
  • 方法的計算時間
  • 隱藏的考察點— setTimeout & cb
// 异步加法
function asyncAdd(a, b, cb){
  setTimeout(() => {
    cb(null, a + b)
  }, Math.random() * 1000)
}

從上述內容來看,最明顯的就是

setTimeout

cb 了,其實這不難理解因為在asyncAdd# 中使用了setTimeout 只能透過回呼函數cb 將本次計算結果回傳出去,那其中的第一個參數null 代表什麼呢? 其實可以認為它是一個錯誤訊息對象,如果你比較了解

node

的話,就會知道在node 中的非同步處理的回呼函數通常第一個參數就是錯誤對象,用於傳遞給外部在發生錯誤時自訂後續執行邏輯等。 一句話:

cb

函數會接收 錯誤物件 和 計算結果 作為參數傳遞給外部。 隱藏的考察點— async & await

<pre class="brush:js;">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] }</pre>

從上述的這部分來看,

sum

方法的回傳值肯定是一個promise類型的,因為最前面明顯的使用了await sum(...) 的形式。 另外

total

函數傳回值也必然是一個promise 類型,因為整個total 函數被定義為了一個async 非同步函數,可點擊此處查看詳細內容。 一句話:

sum

需要回傳promise 類型的值,也就是sum 一定會使用到promise,並且由sum(1,2,3,4,5,6,4) 可知sum 可接收任意長度的參數。 實作asyncAdd

具體實作

實作想法如下:

考慮到外部參數長度不固定,使用剩餘運算子接收所有傳入的參數
  • 考慮到
  • asyncAdd
  • 中的非同步操作,將其封裝為Promise 的實現,即caculate 函數考慮到
  • asyncAdd
  • 實際上只能一次接收兩個數字進行計算,使用循環的形式將多個參數分別傳入考慮到透過循環處理非同步操作的順序問題,使用
  • async/await
  • 來確保正確的執行順序,且async 函數的回傳值剛好符合sumPromise 類型的要求
  • 具體程式碼如下:
// 通过 ES6 的剩余运算符(...) 接收外部传入长度不固定的参数
async function sum(...nums: number[]) {
    // 封装 Promise 
    function caculate(num1: number, num2: number) {
        return new Promise((resolve, reject) => {
            // 调用 asyncAdd 实现加法
            asyncAdd(num1, num2, (err: any, rs: number) => {
                // 处理错误逻辑
                if (err) {
                    reject(err);
                    return;
                }
                // 向外部传递对应的计算结果
                resolve(rs);
            });
        })
    }
    let res: any = 0;
    // 通过遍历将参数一个个进行计算
    for (const n of nums) {
        // 为了避免异步执行顺序问题,使用 await 等待执行结果 
        res = await caculate(res, n);
    }
    return res;
}

進行最佳化

抽離內層函數

    caculate
  • 函數可抽離到sum 函數外層
  • asyncAdd
  • 函數的回呼函數沒必要抽離,因為它所依賴的參數和外部方法太多 #
    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;
    }
  • 快取計算結果

其實你仔細觀察

total

方法,其中sum 呼叫了兩次,而且參數還是一模一樣的,目的就是提示你在第二次計算相同內容時結果直接從快取中獲取,而不是在透過非同步計算。 <pre class="brush:js;">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] }</pre>以下只是一個簡單的快取方案的實現,不必過於糾結,具體實現如下:

const cash: any = {};
function isUndefined(target: any) {
    return target === void 0;
}
async function sum(...nums: number[]) {
    let res: any = 0;
    const key = nums.join(&#39;+&#39;);
    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视频教程web前端

以上是JavaScript介紹之手寫非同步加法asyncAdd方法的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:jb51.net。如有侵權,請聯絡admin@php.cn刪除