我想创建一个公开以下接口的对象:
// Create the object that counts to three
const c = counter(3);
// c.finished is a promise that resolves when c.count() is invoked three times
c.finished.then(() => console.log('counted three times!'));
// Somewhere else, c.count() is invoked in async body
setTimeout(() => c.count(), 500);
setTimeout(() => c.count(), 1000);
setTimeout(() => c.count(), 1500);
我希望c.finished
在 1.5 秒后解决。
如何仅使用本机Promise
API编写counter(countTimes)
?
披露我已经有解决了上述问题,想知道什么是最优雅的方法。
编辑
我最初的解决方案是:
class AsyncCounter {
constructor(countTimes) {
let currentCount = 0;
this.countTimes = countTimes;
this.ready = new Promise(resolveReady => {
this.finished = new Promise(resolveFinished => {
const count = () => {
currentCount++;
if (currentCount >= this.countTimes) {
resolveFinished();
}
return currentCount;
};
this.count = () => this.ready.then(() => count());
resolveReady();
});
});
}
}
const counter = countTimes => new AsyncCounter(countTimes);
正如@Bergi所建议的,并根据执行器功能的MDN文档:
在 Promise 构造函数甚至返回 创建的对象
因此,上述解决方案中的ready
承诺是不必要的。
你会写
function counter(n) {
let i=0, resolve;
return {
count() {
if (++i == n) resolve();
},
finished: new Promise(res => {
resolve = res;
})
};
}
或者,与其将resolve
放在外部变量中,您也可以这样做
function counter(n) {
let i=0;
const res = {};
res.finished = new Promise(resolve => {
res.count = () => {
if (++i == n) resolve();
};
});
return res;
}
以下是我可能编写它的方式,但是将resolveInternal
提取到外部resolve
变量中让我觉得必须有更好的解决方案。遗憾的是,本机Promise
API 不会公开任何方法来外部解析 promise 对象。
function counter(max) {
let resolve = null;
const finished = new Promise(resolveInternal => {
resolve = resolveInternal
})
const count = () => {
if (!--max) resolve()
}
return {
count,
finished
}
}
const c = counter(3)
c.finished.then(() => console.log("counted three times!"))
setTimeout(() => c.count(), 500)
setTimeout(() => c.count(), 1000)
setTimeout(() => c.count(), 1500)