成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

有趣的 Async hooks 模塊

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

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

AsyncLocalStorage

在 Node.js 中,上下文傳遞一直是一個(gè)非常困難的問(wèn)題,Node.js 通過(guò) AsyncLocalStorage 提供了一種解決方案,今天看到一個(gè)庫(kù)中實(shí)現(xiàn)了類(lèi)似 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)里就可以通過(guò) context 函數(shù)獲取到當(dāng)前的上下文,實(shí)際上獲取的就是剛才壓入棧中的內(nèi)容,執(zhí)行完回調(diào)后再出棧。前面介紹了其工作原理,主要是實(shí)現(xiàn)異步資源的上下文傳遞且在執(zhí)行回調(diào)時(shí)通過(guò)棧的方式實(shí)現(xiàn)了上下文的管理,那么第一個(gè)上下文是如何來(lái)的呢?答案是通過(guò) run 函數(shù)(Node.js 中還可以通過(guò) enterWith),run 會(huì)把用戶(hù)設(shè)置的上下文壓入棧中,然后執(zhí)行了一個(gè)用戶(hù)傳入的函數(shù),如果這個(gè)函數(shù)中創(chuàng)建了異步資源,那么用戶(hù)傳入的上下文就會(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)原理非常簡(jiǎ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é)任編輯:武曉燕 來(lái)源: 編程雜技
相關(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開(kāi)發(fā)

2020-10-28 09:12:48

React架構(gòu)Hooks

2021-01-27 08:05:55

本地存儲(chǔ)HTTP

2019-08-20 15:16:26

Reacthooks前端

2014-09-19 11:17:48

面試題

2010-07-17 01:03:13

CMD Telnet

2022-03-31 17:54:29

ReactHooks前端

2020-09-19 17:46:20

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

2016-10-21 10:15:53

2023-03-13 08:47:06

CSS數(shù)學(xué)函數(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ù)

2021-03-18 08:00:55

組件Hooks React

2024-11-07 12:47:51

hook函數(shù)git

2022-04-16 20:10:00

React Hookfiber框架

2022-08-21 09:41:42

ReactVue3前端
點(diǎn)贊
收藏

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

主站蜘蛛池模板: 国产精品视频 | 亚洲精品视频一区 | 91免费版在线观看 | 中文字幕第十五页 | 午夜免费观看体验区 | 麻豆av网站 | 欧美一级二级在线观看 | 狠狠操天天操 | 久久精品一 | 久久久久久国产精品免费免费狐狸 | 国产综合第一页 | 国产特一级黄色片 | 日韩午夜影院 | 99久久精品免费看国产小宝寻花 | 我爱操| 久久99久久久久 | 国产成人免费 | 中文字幕成人在线 | 99精品在线观看 | 久久久久久久久久毛片 | 国产精品一区二区久久 | 久久一区二区三区四区 | 日韩一区二区三区在线看 | 蜜桃视频成人 | 欧美一区二区大片 | 欧美国产视频 | 国产一区二区影院 | 在线观看欧美日韩视频 | 99久久成人 | 成人在线观 | 毛片站| 国产传媒在线观看 | 国产激情视频在线观看 | 日韩av视屏| 久久伊人免费视频 | 香蕉久久a毛片 | 国产精品色av | 嫩草研究影院 | 亚洲www啪成人一区二区 | 亚洲美女天堂网 | 国产精品久久久久久妇女 |