【发布时间】:2019-02-10 20:05:54
【问题描述】:
我有一系列要并行调用的 promise,但要同步解决。
我编写了这段代码来完成所需的任务,但是,我需要创建自己的对象 QueryablePromise 来包装本机 Promise,我可以同步检查它的已解决状态。
有没有更好的方法来完成这个不需要特殊对象的任务?
请注意。我不想使用
Promise.all,因为我不想在处理承诺的效果之前等待所有承诺解决。而且我不能在我的代码库中使用async函数。
const PROMISE = Symbol('PROMISE')
const tap = fn => x => (fn(x), x)
class QueryablePromise {
resolved = false
rejected = false
fulfilled = false
constructor(fn) {
this[PROMISE] = new Promise(fn)
.then(tap(() => {
this.fulfilled = true
this.resolved = true
}))
.catch(x => {
this.fulfilled = true
this.rejected = true
throw x
})
}
then(fn) {
this[PROMISE].then(fn)
return this
}
catch(fn) {
this[PROMISE].catch(fn)
return this
}
static resolve(x) {
return new QueryablePromise((res) => res(x))
}
static reject(x) {
return new QueryablePromise((_, rej) => rej(x))
}
}
/**
* parallelPromiseSynchronousResolve
*
* Call array of promises in parallel but resolve them in order
*
* @param {Array<QueryablePromise>} promises
* @praram {Array<fn>|fn} array of resolver function or single resolve function
*/
function parallelPromiseSynchronousResolve(promises, resolver) {
let lastResolvedIndex = 0
const resolvePromises = (promise, i) => {
promise.then(tap(x => {
// loop through all the promises starting at the lastResolvedIndex
for (; lastResolvedIndex < promises.length; lastResolvedIndex++) {
// if promise at the current index isn't resolved break the loop
if (!promises[lastResolvedIndex].resolved) {
break
}
// resolve the promise with the correct resolve function
promises[lastResolvedIndex].then(
Array.isArray(resolver)
? resolver[lastResolvedIndex]
: resolver
)
}
}))
}
promises.forEach(resolvePromises)
}
const timedPromise = (delay, label) =>
new QueryablePromise(res =>
setTimeout(() => {
console.log(label)
res(label)
}, delay)
)
parallelPromiseSynchronousResolve([
timedPromise(20, 'called first promise'),
timedPromise(60, 'called second promise'),
timedPromise(40, 'called third promise'),
], [
x => console.log('resolved first promise'),
x => console.log('resolved second promise'),
x => console.log('resolved third promise'),
])
<script src="https://codepen.io/synthet1c/pen/KyQQmL.js"></script>
为任何帮助干杯。
【问题讨论】:
-
考虑创建一个 Promise 数组,其中每个 Promise 都包含其效果并将该数组传递给
Promise.all。 -
@cartant 谢谢你的评论,你有一个例子说明它是如何工作的吗?
-
“有没有更好的方法来完成这个不需要特殊对象的任务?”“更好”是什么意思 ?为什么您认为需要“特殊对象”?
-
我相信特殊对象是必需的,因为我需要与上面的代码同步检查承诺的状态,你不能用原生
Promise做到这一点,因此我需要用 @987654329 包装它@ 这使我能够在回调中检查promise.resolved。我的意思是不必包装承诺更好,我想知道是否有功能性 js 代码约定或特定对象可以完成任务,或者是否有一个经过测试的库可以用来执行相同的任务。 -
@guest271314 实际上我认为你是对的,我用
QueryablePromise使代码过于复杂我只是在内部使用了一个数组来保存结果,然后检查该数组的承诺状态而不是拥有承诺本身的状态。
标签: javascript asynchronous promise synchronous