国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 編程 > JavaScript > 正文

ES6記錄異步函數(shù)的執(zhí)行時(shí)間詳解

2019-11-20 09:07:04
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

calc

calc 是一個(gè)我們想要做剖析(性能分析)的異步函數(shù)。按照慣例,它的最后一個(gè)參數(shù)是一個(gè)callback。我們像這樣使用 calc

calc(arg, (err, res) => console.log(err || res))

或許,最簡(jiǎn)單的對(duì) calc 這樣的函數(shù)來(lái)剖析性能的方法是,增加一個(gè)計(jì)時(shí)邏輯到我們需要分析的地方:

const t0 = Date.now()calc(arg, (err, res) => { const t1 = Date.now()  console.log(`Log: time: ${t1 = t0}`) console.log(err || res)})

但是,這不是一個(gè)可復(fù)用的解決方案。每一次我們想要對(duì)一個(gè)函數(shù)計(jì)時(shí),我們得引入一個(gè) t0 在外層作用域并且改變 callback 來(lái)測(cè)量和記錄時(shí)間。

對(duì)我來(lái)說(shuō)理想的方式是能夠僅僅通過(guò)包裝一個(gè)異步函數(shù)就能夠?qū)λM(jìn)行計(jì)時(shí):

timeIt(calc)(arg, (err, res) => console.log(err || res))

timeIt 需要能夠很好地對(duì)每一個(gè)異步函數(shù)完成剖析和記錄執(zhí)行時(shí)間。

注意到 timeIt(calc) 有與原始的 calc 函數(shù)同樣的函數(shù)簽名,即它們接受同樣的參數(shù)和返回同樣的值,它只是增加了一個(gè)特性到 cale 上(能夠被記錄時(shí)間的特性)。

calc 和 timeIt(calc) 在任意時(shí)刻可以相互替代。

timeIt 本身是一個(gè)高階函數(shù),因?yàn)樗邮芤粋€(gè)函數(shù)并返回一個(gè)函數(shù)。在我們的例子里,它接受 calc 異步函數(shù),并返回一個(gè)函數(shù)與 calc 有同樣的參數(shù)和返回值。

下面演示我們?nèi)绾螌?shí)現(xiàn) timeIt 函數(shù):

const timeIt = R.curry((report, f) => (...args) => { const t0 = Date.now() const nArgs = R.init(args) const callback = R.last(args) nArgs.push((...args) => { const t1 = Date.now() callback(...args) report(t1 - t0, ...args) }) f(...nArgs)})const timeIt1 = timeIt( (t, err, res) => console.log(`Log: ${err || res} produced after: ${t}`))const calc = (x, y, z, callback) => setTimeout(() => callback(null, x * y / z), 1000)calc(18, 7, 3, (err, res) => console.log(err || res))timeIt1(calc)(18, 7, 3, (err, res) => console.log(err || res))

這個(gè) timeIt 實(shí)現(xiàn)接受兩個(gè)參數(shù):

      report: 一個(gè)函數(shù)用來(lái)生成剖析結(jié)果

      f: 我們想要做剖析的異步函數(shù)

timeIt1 是一個(gè)方便實(shí)用的功能函數(shù),它只是用 console.log 記錄時(shí)間測(cè)量結(jié)果。我們通過(guò)給更通用的 timeIt 函數(shù)傳入 report 參數(shù)來(lái)定義它。

我們實(shí)現(xiàn)了目標(biāo),現(xiàn)在我們可以?xún)H僅將異步函數(shù)包裝在 timeIt1 中就可以對(duì)它計(jì)時(shí)了:

timeIt1(calc)(18, 7, 3, (err, res) => console.log(err || res))

通用的 timeIt 函數(shù)接收一個(gè) report 回調(diào)函數(shù)和一個(gè)異步函數(shù)并返回一個(gè)新的異步函數(shù),這個(gè)異步函數(shù)與原函數(shù)有同樣的參數(shù)和返回值。我們可以這么使用:

timeIt( (time, ...result) => // report callback: log the time , asyncFunc)( parameters…,  (...result) => // result of the async function)

現(xiàn)在讓我們深入 timeIt 的實(shí)現(xiàn)。我們可以簡(jiǎn)單地生成一個(gè)通用函數(shù)類(lèi)似 timeIt1,因?yàn)?timeIt 使用 R.curry 科里化了。

我不打算在這篇文章里討論科里化,但是下面這段代碼演示了科里化的主要用法:

const f = R.curry((x, y) => x + y)f(1, 10) // == 11f(1)(10) // == 11const plus1 = f(1)plus1(10) // == 11

另一方面,這種方式實(shí)現(xiàn)的 timeIt 有幾個(gè)問(wèn)題:

(...args) => { const t1 = Date.now() callback(...args) report(t1 ― t0, ...args)}

這是一個(gè)匿名函數(shù)(又名 lambda,callback),它在原函數(shù)異步執(zhí)行之后被調(diào)用。主要的問(wèn)題是這個(gè)函數(shù)沒(méi)有處理異常的機(jī)制。如果 callback 拋出異常,report 就永遠(yuǎn)不會(huì)被調(diào)用。

我們可以添加一個(gè) try / catch 到這個(gè) lambda 函數(shù)里,然而問(wèn)題的根源是 callback report 是兩個(gè) void 函數(shù),它們沒(méi)有關(guān)聯(lián)在一起。timeIt 包含兩個(gè)延續(xù)(continuations)(report callback)。如果我們只是在 console 下記錄執(zhí)行時(shí)間或者如果我們確定不論 report 還是 callback 都不會(huì)拋出異常,那么一切正常。但是如果我們想要根據(jù)剖析結(jié)果來(lái)執(zhí)行一些行為(所謂的自動(dòng)擴(kuò)容)那么我們需要強(qiáng)化和厘清我們的程序中的延續(xù)序列。

好了,以上這篇文章的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)和工作有所幫助,如果有疑問(wèn)可以留言交流。

發(fā)表評(píng)論 共有條評(píng)論
用戶(hù)名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 高台县| 黄骅市| 安丘市| 石城县| 乌拉特后旗| 大邑县| 吉隆县| 瑞昌市| 黎平县| 婺源县| 康马县| 江永县| 丰都县| 昌宁县| 凤庆县| 什邡市| 洪雅县| 通城县| 靖宇县| 贺兰县| 石河子市| 水富县| 平泉县| 孙吴县| 弥勒县| 江达县| 陈巴尔虎旗| 丹凤县| 太仆寺旗| 城口县| 增城市| 淅川县| 鹿泉市| 阜城县| 盐城市| 延边| 五华县| 奉节县| 石台县| 河北省| 桑植县|