不使用async/await如何实现仅用局部变量存结果的Promise串行调用times函数
实现方案
你需要的仅使用函数局部变量存储结果、不破坏原有函数签名、不依赖async/await的实现如下:
const times = (fn: (...args: any) => Promise<any>, n: number = 1) => { // 仅当前times调用生效的局部结果数组,多次调用times互不干扰 const results: any[] = [] // 内部递归辅助函数处理串行调用逻辑 const step = (remaining: number): Promise<any[]> => { if (remaining === 0) return Promise.resolve(results) return fn().then(res => { results.push(res) return step(remaining - 1) }) } return step(n) }
方案说明
- 完全满足所有约束:没有使用模块级全局变量、没有修改原函数签名、没有使用async/await语法、没有在函数对象上挂载额外属性
- 解决了原实现的隐藏问题:原实现挂载在函数上的
results是共享属性,多次调用times会出现结果互相污染的情况,本实现的results是每次调用times的局部变量,不同调用完全隔离 - 串行逻辑保持不变:必须等前一次
fn返回的Promise状态变为fulfilled后,才会触发下一次fn调用,执行顺序完全符合要求
测试验证
你原来的使用示例无需修改即可直接运行:
const createPromise = (args: any) => new Promise((resolve) => { setTimeout(() => { console.log(`[${new Date().toISOString()}]args: `, args); resolve(args); }, 1000); }); async function test() { const actual = await times(() => createPromise('data'), 3); console.log(actual); // 输出: [ 'data', 'data', 'data' ] } test()
如果要避免测试代码使用async/await,也可以写成Promise链式调用的形式:
times(() => createPromise('data'), 3).then(actual => { console.log(actual); // 输出: [ 'data', 'data', 'data' ] })
内容的提问来源于stack exchange,提问作者Lin Du
相关产品推荐
相关产品推荐

