let textProcess = new Promise((resolve, reject) => {
let text
try {
// fetch text from the internet
text = "str"
resolve(text)
} catch (e) {
reject("failed to fetch!")
}
})
textProcess.then(data => {
let json
try {
json = JSON.parse(data)
} catch (e) {
console.error("failed to parse!")
// ..........i want to end the whole process here, never go ahead
}
}, e => {
// try to fetch text from local chache
}).then(json => {
// work on the json obj
}, e => {
// if failed to fetch from local too, just let it go
})
有没有办法结束一条可循环的链条?
看上面的例子,我想在解析失败时结束整个过程(以“ ..........”开头的行)。但是实际上,最后一个仍然会被调用。
实现我的目标的正确而优雅的方法是什么?
答案 0 :(得分:1)
您的Promise用法涉及很多次优模式。修复它们实际上也会带来您想要实现的目标。
textProcess.then(data => {
// 1st anti-pattern fix
// any error triggered here
// also gets caught at the end catch
return JSON.parse(data)
}).then(json => {
// work on json obj
}).catch(e => {
// 2nd anti-pattern fix
// one catch for the whole thenable chain
console.error("Failed to parse!", e)
})
通过这种方式,您可以适当地利用Javascript Promise提供的功能,并根据需要使用一个简单的.catch
。
编辑-有关Promise反模式的一些解释
标记的1st anti-pattern
与try..catch
中不必要的嵌套then
块有关。在其中,您可以同步返回(甚至undefined
),另一个Promise(都为thenable
)或抛出错误(将被catch
捕获)。基本上,您不需要显式捕获它,而让它“流过”。
上面提到的2nd anti-pattern
是一个事实,在大多数使用情况下,第二个参数-then
的拒绝处理程序被认为是次优的。一个Promise链应该利用一个catch
来简化工作流程。
但是,在极少数需要执行“早期捕获”和“恢复”的情况下,请考虑以下方法,该方法仍然比对then
使用两个处理程序要清楚一些:
textProcess.then(data => {
return parser1(data)
}).catch(e => {
console.log("First parser failed")
// for example first parser failed
return "fallback data"
}).then(data => {
// process received data as "fallback data"
}).catch(e => {
// always have a "last resort" catch at the end of the workflow
})
答案 1 :(得分:0)
简短的回答是“否”,没有机制可以在then
处理程序中终止链的一半。 (在2016年向TC39委员会提出了取消承诺的提案,但后来被撤回了。)
请注意,“承诺链” 通常是指承诺
在串联在一起的单个promise方法调用链中,由最后个then
,catch
或finally
调用返回。
当执行定义链的代码时,对上面列出的promise方法的所有调用都是同步进行的。执行后,将创建链中的所有promise,并调用链中的所有方法调用。
由于promise只有三种状态(未决,已实现和已拒绝),因此您最好的办法是安排“取消”在链接的promise的拒绝通道中发送,并根据需要忽略它。 (没有标准的“已取消”拒绝值可以使用)。