前端JavaScript基础训练系列一百六十五:promise 的 then(..)

如果这个 Promise 链中的某个步骤出错了怎么办?错误和异常是基于每个 Promise 的,这 意味着可能在链的任意位置捕捉到这样的错误,而这个捕捉动作在某种程度上就相当于在 这一位置将整条链“重置”回了正常运作:

// 步骤1:
request( "http://some.url.1/" )
// 步骤2:
.then( function(response1){
foo.bar(); // undefined,出错!
// 永远不会到达这里
return request( "http://some.url.2/?v=" + response1 ); })
// 步骤3: .then(
function fulfilled(response2){ // 永远不会到达这里
},
// 捕捉错误的拒绝处理函数 function rejected(err){ console.log( err );
// 来自foo.bar()的错误TypeError
return 42; }
)
// 步骤4:
.then( function(msg){
    console.log( msg );
} );
// 42

第 2 步出错后,第 3 步的拒绝处理函数会捕捉到这个错误。拒绝处理函数的返回值,如果有的话,会用来完成交给下一个步骤的 promise,这样,这 个链现在就回到了完成状态。
正如之前讨论过的,当从完成处理函数返回一个 promise 时,它会被展开并 有可能延迟下一个步骤。从拒绝处理函数返回 promise 也是如此,因此如果 在第 3 步返回的不是 42 而是一个 promise 的话,这个 promise 可能会延迟第 4 步。调用 then(…) 时的完成处理函数或拒绝处理函数如果抛出异常,都会 导致(链中的)下一个 promise 因这个异常而立即被拒绝。
如果你调用 promise 的 then(…),并且只传入一个完成处理函数,一个默认拒绝处理函数 就会顶替上来:

var p = new Promise( function(resolve,reject){
          reject( "Oops" );
} );
      var p2 = p.then(
          function fulfilled(){
// 永远不会达到这里 }
// 假定的拒绝处理函数,如果省略或者传入任何非函数值 // function(err) {
// throw err;
// }
);

如你所见,默认拒绝处理函数只是把错误重新抛出,这最终会使得 p2(链接的 promise) 用同样的错误理由拒绝。从本质上说,这使得错误可以继续沿着 Promise 链传播下去,直 到遇到显式定义的拒绝处理函数。
稍后我们会介绍关于 Promise 错误处理的更多细节,因为还有其他一些微妙 的细节需要考虑。
如果没有给 then(…) 传递一个适当有效的函数作为完成处理函数参数,还是会有作为替代 的一个默认处理函数:

var p = Promise.resolve( 42 );
p.then(
// 假设的完成处理函数,如果省略或者传入任何非函数值 // function(v) {
// return v;
// }
null,
function rejected(err){
// 永远不会到达这里 }
);

你可以看到,默认的完成处理函数只是把接收到的任何传入值传递给下一个步骤 (Promise)而已。

让我们来简单总结一下使链式流程控制可行的 Promise 固有特性。
• 调用 Promise 的 then(…) 会自动创建一个新的 Promise 从调用返回。
• 在完成或拒绝处理函数内部,如果返回一个值或抛出一个异常,新返回的(可链接的)
Promise 就相应地决议。
• 如果完成或拒绝处理函数返回一个 Promise,它将会被展开,这样一来,不管它的决议
值是什么,都会成为当前 then(…) 返回的链接 Promise 的决议值。

尽管链式流程控制是有用的,但是对其最精确的看法是把它看作 Promise 组合到一起的一 个附加益处,而不是主要目的。正如前面已经多次深入讨论的,Promise 规范化了异步, 并封装了时间相关值的状态,使得我们能够把它们以这种有用的方式链接到一起。

当然,相对于讨论的回调的一团乱麻,链接的顺序表达(this-then-this-then-this…) 已经是一个巨大的进步。但是,仍然有大量的重复样板代码(then(…) 以及 function() { … })。我们将会看到在顺序流程控制表达方面提升巨大的优美模式,通 过生成器实现。

  • 5
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值