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

有趣的 Async hooks 模塊

開發(fā) 前端
在 Node.js 中,上下文傳遞一直是一個(gè)非常困難的問題,Node.js 通過 AsyncLocalStorage 提供了一種解決方案,今天看到一個(gè)庫中實(shí)現(xiàn)了類似 AsyncLocalStorage 的能力,還挺有意思的。

在 Node.js 中,Async hooks 是一個(gè)非常有意思且強(qiáng)大的模塊(雖然性能上存在一些問題),在 APM 中,我們可以借助這個(gè)模塊做很多事情。本文介紹兩個(gè)有趣的用法。

AsyncLocalStorage

在 Node.js 中,上下文傳遞一直是一個(gè)非常困難的問題,Node.js 通過 AsyncLocalStorage 提供了一種解決方案,今天看到一個(gè)庫中實(shí)現(xiàn)了類似 AsyncLocalStorage 的能力,還挺有意思的。代碼如下。

class ALS {
    constructor() {
        this._contexts = new Map();
        this._stack = [];
        this.hook = createHook({
            init: this._init.bind(this),
            before: this._before.bind(this),
            after: this._after.bind(this),
            destroy: this._destroy.bind(this),
        });
    }

    context() {
        return this._stack[this._stack.length - 1];
    }

    run(context, fn, thisArg, ...args) {
        this._enterContext(context);
        try {
            return fn.call(thisArg, ...args);
        }
        finally {
            this._exitContext();
        }
    }

    enable() {
        this.hook.enable();
    }

    disable() {
        this.hook.disable();
        this._contexts.clear();
        this._stack = [];
    }

    _init(asyncId) {
        const context = this._stack[this._stack.length - 1];
        if (context !== undefined) {
            this._contexts.set(asyncId, context);
        }
    }

    _destroy(asyncId) {
        this._contexts.delete(asyncId);
    }

    _before(asyncId) {
        const context = this._contexts.get(asyncId);
        this._enterContext(context);
    }

    _after() {
        this._exitContext();
    }

    _enterContext(context) {
        this._stack.push(context);
    }

    _exitContext() {
        this._stack.pop();
    }
}

這個(gè)方式是基于 Async hooks 實(shí)現(xiàn)的,原理是在 init 鉤子中獲取當(dāng)前的上下文,然后把當(dāng)前的上下文傳遞到當(dāng)前創(chuàng)建的異步資源的,接著在執(zhí)行異步資源回調(diào)前,Node.js 會(huì)執(zhí)行 before 鉤子,before 鉤子中會(huì)把當(dāng)前異步資源(正在執(zhí)行回調(diào)的這個(gè)資源)的上下文壓入棧中,然后在回調(diào)里就可以通過 context 函數(shù)獲取到當(dāng)前的上下文,實(shí)際上獲取的就是剛才壓入棧中的內(nèi)容,執(zhí)行完回調(diào)后再出棧。前面介紹了其工作原理,主要是實(shí)現(xiàn)異步資源的上下文傳遞且在執(zhí)行回調(diào)時(shí)通過棧的方式實(shí)現(xiàn)了上下文的管理,那么第一個(gè)上下文是如何來的呢?答案是通過 run 函數(shù)(Node.js 中還可以通過 enterWith),run 會(huì)把用戶設(shè)置的上下文壓入棧中,然后執(zhí)行了一個(gè)用戶傳入的函數(shù),如果這個(gè)函數(shù)中創(chuàng)建了異步資源,那么用戶傳入的上下文就會(huì)傳遞到這個(gè)新創(chuàng)建的異步資源中,后面執(zhí)行這個(gè)異步資源的回調(diào)時(shí),就可以拿到對(duì)應(yīng)的上下文了。接著看一下使用效果。

const als = new ALS();
als.enable();

http.createServer((req, res) => {
    als.run(req, () => {
        setImmediate(() => {
            console.log(als.context().url);
            res.end();
        });
    })
}).listen(9999, () => {
    http.get({ port: 9999, host: '127.0.0.1' });
});

執(zhí)行上面代碼會(huì)輸出 /。可以看到在 setImmediate 的回調(diào)中(setImmediate 會(huì)創(chuàng)建一個(gè)異步資源)成功拿到了 run 時(shí)設(shè)置的上下文。

監(jiān)控異步回調(diào)的耗時(shí)

在 Node.js 中,代碼執(zhí)行耗時(shí)是一個(gè)非常值得關(guān)注的地方,Node.js 也提供了很多手段采集代碼執(zhí)行的耗時(shí)信息,下面介紹的是基于 Async hooks 實(shí)現(xiàn)的回調(diào)函數(shù)耗時(shí)監(jiān)控。

const { createHook } = require('async_hooks');
const fs = require('fs');

const map = {};

createHook({
    init: (asyncId) => {
        map[asyncId] = { stack: new Error().stack };
    },
    before: (asyncId) => {
        if (map[asyncId]) {
            map[asyncId].start = Date.now();
        }
    },
    after: (asyncId) => {
        if (map[asyncId]) {
            fs.writeFileSync(1, `callback cost: ${Date.now() - map[asyncId].start}, stack: ${map[asyncId].stack}`);
        }
    },
    destroy: (asyncId) => {
        delete map[asyncId];
    }
}).enable();

setTimeout(() => {
    for (let i = 0; i < 1000000000; i++) {

    }
});

實(shí)現(xiàn)原理非常簡單,主要是利用 before 和 after 鉤子實(shí)現(xiàn)了回調(diào)的耗時(shí)統(tǒng)計(jì),就不多介紹,社區(qū)中也有同學(xué)實(shí)現(xiàn)了這個(gè)能力,具體可以參考 https://github.com/naugtur/blocked-at/tree/master。


責(zé)任編輯:武曉燕 來源: 編程雜技
相關(guān)推薦

2021-01-26 08:07:44

Node.js模塊 Async

2021-08-12 01:00:29

NodejsAsync

2021-05-21 06:13:35

React Hooks react-refrReact

2023-11-06 08:00:00

ReactJavaScript開發(fā)

2021-01-27 08:05:55

本地存儲(chǔ)HTTP

2020-10-28 09:12:48

React架構(gòu)Hooks

2019-08-20 15:16:26

Reacthooks前端

2022-03-31 17:54:29

ReactHooks前端

2010-07-17 01:03:13

CMD Telnet

2014-09-19 11:17:48

面試題

2023-03-13 08:47:06

CSS數(shù)學(xué)函數(shù)

2016-10-21 10:15:53

2020-09-19 17:46:20

React Hooks開發(fā)函數(shù)

2014-07-15 10:31:07

asyncawait

2016-11-22 11:08:34

asyncjavascript

2025-03-06 03:00:00

hook??復(fù)數(shù)函數(shù)

2022-08-21 09:41:42

ReactVue3前端

2022-10-10 23:19:02

Python腳本語言工具庫

2021-08-05 05:02:04

DPU數(shù)據(jù)中心Pensando

2014-01-22 09:46:42

JavaScript數(shù)組
點(diǎn)贊
收藏

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