我正在研究一个受此答案启发的承诺链: https://stackoverflow.com/a/44955506/7485805
我想打破此for循环,以正确处理链条的拒绝。我只是发现不能在链的break
方法内使用.catch
。
如果有帮助,这是我的代码:
function pro (arr) {
let chain = Promise.resolve();
const self = {req: {}, res: {}};
const length = arr.length;
return new Promise((resolve, reject) => {
for(let i=0; i<length; i++){
chain = chain
.then(() => arr[i].call(self) )
.then(() => {
if(i === (length - 1) )
resolve();
})
.catch(e => {
reject(e);
})
}
})
.then(() => {
return self
})
.catch(e => {
throw new Error (e);
})
}
const x = function () {
const self = this;
return new Promise(resolve => {
self.req = {key: "value"}
resolve();
})
}
const y = function () {
const self = this;
return new Promise((resolve, reject) => {
console.log(self);
reject();
})
}
const z = function () {
const self = this;
return new Promise((resolve, reject) => {
console.log('failed');
})
}
pro([x, y, z])
.then((self) => {
console.log('final',self);
})
.catch(e => {
console.log('error', e);
})
x, y, z
是在函数pro
中链接在一起的三个函数
x
成功解析后,y
被执行但被拒绝。
我想停止执行z
,因为继续执行毫无意义,并可能在实际代码中产生错误。
此外,如果有人可以为我推荐这段代码更好的版本:
.then(() => {
if(i === (length - 1) )
resolve();
})
注意:我不能使用await
,因为此代码将在服务器端执行,并且使用await
可能会阻止其他传入请求。
答案 0 :(得分:2)
使用async/await
语法要容易得多:
async function pro(arr) {
const self = {req: {}, res: {}};
for(const f of arr) await f.call(self);
return self;
}
async function pro(arr) {
const self = {req: {}, res: {}};
for(const f of arr) await f.call(self);
return self;
}
const x = function () {
const self = this;
return new Promise(resolve => {
self.req = {key: "value"}
resolve();
})
}
const y = function () {
const self = this;
return new Promise((resolve, reject) => {
console.log(self);
reject("y failed");
})
}
const z = function () {
const self = this;
return new Promise((resolve, reject) => {
console.log('failed');
})
}
pro([x, y, z]).then((self) => {
console.log('final',self);
})
.catch(e => {
console.log('error', e);
});
答案 1 :(得分:1)
几件事:当您在for循环中构造您的Promise链时,就是这样:构建链。 .then
执行最早在下一个事件循环中发生。我将尝试说明:
var promiseChain = functionReturningPromise();
for(var i=0;i<3;i++){
promiseChain = promiseChain.then(x=> {
return anotherPromiseFunction(x);
});
}
取决于functionReturningPromise
的实际作用,此时可能已经发生了某些事情……也许没有。例如,我们可能已经开始fetch
,或者可能已经开始WebWorker.
,但是如果我们在第一个Promise中嵌套了setTimeout
,那么我们所做的就是将{{1在事件循环的下一个循环中回调到队列中。但保证100%,尚未运行setTimeout
函数。稍后,在下一个事件循环中。
因此,下一个事件循环到来,并且承诺已经解决。这意味着下一个.then
将开始运行。假设失败了。那时,由于我们链接了承诺(.then
,因此我们立即跳到了链中的第一个promiseChain = promiseChain.then
(或带有第二个参数的.catch
),以及所有中间的{{1 }} s被完全跳过而不执行。或者,如果没有.then
,那么这个诺言链就完成了。无需休息;这就是Promises的工作方式。
因此,如果您仅在链的末尾添加一个.then
,那就太好了。
关于“事件循环”的事情:我真的建议观看来自JSConf.Asia 2018的Jake Archibald: In The Loop。
大约catch
...听起来好像有些混乱。您只能在.catch
函数的内部{strong}内部使用{strong},因此永远不能只使用一个await
就完全阻止线程执行。它的工作就像链接await
一样,只是语法糖。因此,@ trincot绝对正确,您将使用该语法更加开心。
答案 2 :(得分:1)
这是一个替代性答案,它只是连续执行诺言,除非诺言被拒绝,然后将其终止。这不使用await,但是应该给您一个大致的思路,如果没有它,该怎么办,但是该代码的编写速度非常快,因此不是最优化的代码。
const x = function() {
return new Promise(resolve => {
resolve('it resolved ma!');
});
};
const y = function() {
const self = this;
return new Promise((resolve, reject) => {
reject("reject");
});
};
const z = function() {
const self = this;
return new Promise((resolve, reject) => {
resolve("never gets executed");
});
};
function runPromises(promises) {
const results = [];
let count = 0;
const executePromise = i => {
count++;
return promises[i]()
.then((response) => {
results.push(response);
if (count !== promises.length) {
executePromise(count);
}
})
.catch((e) => {
results.push(e);
console.log("stop right now, thank you very much");
});
};
if (Array.isArray(promises)) {
executePromise(count);
}
return results;
}
const results = runPromises([x, y, z]);
console.log(results);