如何查找JavaScript Promise的创建位置?
问题
在JavaScript Promise中,如何在其resolved处理器中(若可行的话)查找该Promise的创建位置?
例如,如下代码(使用async/await情况类似),当代码在debugger语句处暂停时,如何查看对应Promise的创建位置:
'use strict'; const promise = getPromise(); handleResolution(promise); function handleResolution(promiseArg) { promiseArg .then((resolution) => { debugger; console.log(`resolved with: ${ resolution }`); }); } function getPromise() { return new Promise((resolve) => { resolve('in getPromise()'); }); }
此时调用栈已无法使用,因为发起异步调用的调用栈已不存在。
是否存在类似查看‘Promise链’的方法?
注:此问题针对通用JavaScript,并非局限于Node.js、Chrome开发者工具等,仅以此栈为例进行演示。
回答
1. 手动给Promise附加创建栈信息
这是通用场景下最可靠的方案,在创建Promise时主动捕获调用栈并挂载到Promise实例上:
'use strict'; function getPromise() { const promise = new Promise((resolve) => { resolve('in getPromise()'); }); // 捕获创建时的调用栈并附加到Promise实例 promise.creationStack = new Error().stack; return promise; } function handleResolution(promiseArg) { promiseArg .then((resolution) => { debugger; // 此时可以直接访问创建栈 console.log('Promise创建位置:', promiseArg.creationStack); console.log(`resolved with: ${ resolution }`); }); } const promise = getPromise(); handleResolution(promise);
这种方式不依赖任何运行环境或调试工具,完全是代码层面的通用实现,能直接拿到Promise创建时的完整调用栈。
2. 封装Promise构造函数统一处理
如果需要全局给所有Promise附加创建栈,可以封装一个自定义Promise构造函数,替代原生的Promise:
'use strict'; class TrackedPromise extends Promise { constructor(executor) { super(executor); this.creationStack = new Error().stack; } } // 使用TrackedPromise替代原生Promise function getPromise() { return new TrackedPromise((resolve) => { resolve('in getPromise()'); }); } function handleResolution(promiseArg) { promiseArg .then((resolution) => { debugger; console.log('Promise创建位置:', promiseArg.creationStack); console.log(`resolved with: ${ resolution }`); }); } const promise = getPromise(); handleResolution(promise);
这样所有通过TrackedPromise创建的实例都会自动携带创建栈信息,适合需要全局追踪的场景。
3. 关于Promise链的追踪
如果要追踪整个Promise链的调用路径,可以在每次调用.then()/.catch()等方法时,把当前调用的栈信息也附加到新生成的Promise实例上:
'use strict'; class TrackedPromise extends Promise { constructor(executor) { super(executor); this.chainStacks = [new Error().stack]; } then(onFulfilled, onRejected) { const newPromise = super.then(onFulfilled, onRejected); newPromise.chainStacks = [...this.chainStacks, new Error().stack]; return newPromise; } catch(onRejected) { const newPromise = super.catch(onRejected); newPromise.chainStacks = [...this.chainStacks, new Error().stack]; return newPromise; } } // 使用示例 function getPromise() { return new TrackedPromise((resolve) => { resolve('in getPromise()'); }); } function handleResolution(promiseArg) { promiseArg .then((res) => { console.log('First then'); return res; }) .then((resolution) => { debugger; // 打印整个Promise链的所有调用栈 console.log('Promise链调用路径:', promiseArg.chainStacks); console.log(`resolved with: ${ resolution }`); }); } const promise = getPromise(); handleResolution(promise);
这种方式可以完整记录从Promise创建到每一步链式调用的位置,方便追踪整个异步流程的执行路径。
以上方案均为通用JavaScript实现,不依赖任何特定运行环境或调试工具,完全符合需求。
内容的提问来源于stack exchange,提问作者d.k
相关产品推荐
相关产品推荐

