首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >当承诺被拒绝时,承诺链顺序有什么关系?

当承诺被拒绝时,承诺链顺序有什么关系?
EN

Stack Overflow用户
提问于 2017-10-11 11:53:06
回答 2查看 84关注 0票数 2

当一个Promise被拒绝,而.then().catch()之后出现时,就会捕捉到拒绝,但是下面仍然会运行(参见下面的then示例)。

但是,当Promise被解析,而.then().catch()之前出现时,拒绝就会被捕获,而.then()永远不会被调用。

为什么这两种情况的行为不同,在什么情况下在被拒绝后调用.then()是有用的呢?

代码语言:javascript
运行
复制
var then = Promise.reject()
    .catch(() => 'catch')
    .then(() => document.getElementById('then').innerHTML = 'then');

var noThen = Promise.reject()
    .then(() => document.getElementById('noThen').innerHTML = 'then')
  .catch((err) => 'catch');

https://jsfiddle.net/mmyj61dd/

编辑:

一个有趣的相关示例演示了.then()如何依赖于传递给它的函数的参数:

代码语言:javascript
运行
复制
var then = Promise.reject()
  .then((undefined, err) => 'catch')
  .then((asdf) => document.getElementById('then').innerHTML = 'then');

var noThen = Promise.reject()
  .then((asdf) => document.getElementById('noThen').innerHTML = 'then')
  .then((undefined, err) => 'catch');

在这两种情况下,只调用(undefined, err) => 'catch'函数。

https://jsfiddle.net/ro0cv1p1/2/

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-10-11 13:46:35

它类似于传统的try..catch

代码语言:javascript
运行
复制
try {
    foo();
    bar();
} catch (e) {
    baz();
}

这不同于:

代码语言:javascript
运行
复制
try {
    foo();
} catch (e) {
    baz();
}

bar();

实际的应用程序很容易解释:尝试某事(开始承诺),如果它失败了会产生一些默认值,然后继续使用异步链。例如:

代码语言:javascript
运行
复制
fetch('http://example.com')
    .then(result => result.somevalue)
    .catch(e => 'default value')
    .then(value => alert(value));

这要么显示从example.com获取的example.com,要么显示default value

票数 2
EN

Stack Overflow用户

发布于 2017-10-11 14:17:31

不会调用任何catch (实际上在then中没有第一个回调,因为第二个回调确实是catch的替代),直到您在链中“捕获拒绝”并返回“正”值-- then 函数应该返回任何未解决的承诺,并且不应该抛出和错误来“修复”该链中的承诺。如果catch将返回这样的值,那么下一个then将被调用,它也将获得作为param的catch的返回值。同样,如果then被调用并抛出错误或返回被拒绝的承诺,则在“捕获拒绝”之前不会调用链中的下一个then

例如。

代码语言:javascript
运行
复制
let resolvedPromiseAfterAll = Promise.reject()
    .then(() => 'then') // <-not called
    .catch(e => { console.log(e); throw e; }) // <- only error log
    .then(() => 'then 2') // <- still not called because previous catch didn't resolve the promise
    .catch(e => 'catched') // <- return 'catched' that is equiv to Promise.resolve('catched')
    .then(val => { console.log('then 2', val); return 'ok'; }) // <-- this promise should finally be called because previous catch didn't throw Error or returned rejected Promise. We also get 'catch' as first param in then callback so the console.log is 'then 2 catched'.

这就是承诺链的工作原理--通过捕捉拒绝原因并返回一些不是错误的内容,您可以从被拒绝的承诺得到解决,还可以通过返回被拒绝的承诺或在附加的then中抛出错误来“破坏”已解决的承诺。

这是非常强大的特性,在您的实现中,您可以决定在拒绝时做什么,所以如果您要做这样的事情(没有catches):somePromise.then().then().then()意味着如果在任何阶段发生错误,您都不想调用任何后续的then回调。但是,如果您想处理某些then上的承诺拒绝,则在这个then之后添加catch

它类似于try/catch --如果在此块中的前一行中抛出异常,则不会调用try块中的部分代码。

顺便说一句,修正了你的小提琴例子:https://jsfiddle.net/ro0cv1p1/3/

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/46687558

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档