JavaScript/V8:使自定义 `.then` 方法与异步堆栈跟踪兼容

问题描述

最近版本的 V8 具有“异步堆栈跟踪”,这意味着如果您使用原生 async/await,即使跨越异步间隙,您也可以获得良好的堆栈跟踪。

当我使用 await 方法而不是 Promise 处理自定义对象时,我正试图弄清楚如何获得良好的堆栈跟踪。

.then

我在 Node 14.15.0 和 Chrome 88.0.4324.150 中得到的堆栈跟踪没有很好的堆栈跟踪:

"use strict";

function gap() {
    return new Promise(resolve => setTimeout(resolve,1));
}

// A class that has it's own 'then' method.
class Blah {
    constructor(f) {
        this.f = f;
    }
    then(onFulfilled,onRejected) {
        this.f()
            .then(r => onFulfilled ? onFulfilled(r) : r)
            .catch(onRejected);
    }
}

async function f3() {
    await gap();
    const blah = new Blah(async () => { throw new Error('blah'); });
    await blah;
}
async function f2() {
    await gap();
    await f3();
}
async function f1() {
    await gap();
    await f2();
}
async function mainAsync() {
    try {
        await f1();
    }
    catch (err) {
        console.log('err',err);
    }
}

if (require.main === module) {
    mainAsync().catch(err => {
        console.error(err);
        process.exit(1);
    });
}

如果我直接从 err Error: blah at Blah.f (main.js:21:47) at Blah.then (main.js:13:14) 抛出异常,我会得到一个很好的堆栈跟踪:

f3()

有没有办法编写自定义err Error: blah at f3 (main.js:19:11) at async f2 (main.js:24:5) at async f1 (main.js:28:5) at async mainAsync (main.js:32:9) 方法,以便获得良好的堆栈跟踪?

我为什么要这样做

自定义对象实际上来自第 3 方数据库查询Mammoth。 Mammoth 提供了一个流利风格的 API 来构建查询,例如.then

要运行查询,您需要 db.select(...).from(...) 查询对象。 (查询对象有一个自定义awaitcode link。)

我正在尝试修改 Mammoth 以在不更改 Mammoth 的公共 API 的情况下产生良好的堆栈跟踪。

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)