在上一篇文章中手写封装了 then 方法,这一篇继续前行,可以在原有封装 then 方法的前提下封装一个 catch 方法,非常简单。
catch 方法接受一个参数,就是失败时的回调,而 then 方法接受两个参数,第二个参数为失败时的回调,那可不可以只使用 then 方法的第二个参数呢?
catch 的功能实现:
先来看一下 catch 的使用方式:
let p = new Promise((resolve, reject) => {reject("NO");
})
p.catch(reason => {console.log(reason); // "NO"
})
Promise.prototype.catch 代码封装如下:
Promise.prototype.catch = function(onRejected){// this就是实例对象 promisereturn this.then(undefined, onRejected);
}
上面代码 then 中第一个参数使用 undefined 占位,就像我们使用 call 以及 apply 时,无绑定 this 形式一样,例如:
fn.call(null, 1, 2, 3)
fn.apply(null, [1, 2, 3])
catch 的链式调用使用方式:
let p = new Promise((resolve, reject) => {reject("NO");
})
// 这里的第一个then方法没有传参,且后面每一个then方法只传了一个回调函数
p.then().then(value=> {console.log(value);
}).then(value=> {console.log(value);
}).catch(reason => {console.log(reason);
})
在上面代码中的第一个 then 方法中没有传递回调函数,这时候咱们封装的 then 方法肯定报错,程序无法执行,因为不传参数,相当于传递两个 undefined 值,undefined 值无法进行函数调用,因为 then 方法内部默认是传递函数作为参数的。这时候就需要在 then 方法中添加未传值时的处理,当 then 中无值或只有一个值时,我们给他一个自定义生成的函数,这样成功和错误的结果会向下传递,不至于报错而终止程序。
还得修改then方法:
Promise.prototype.then = function(onResolved, onRejected){// 若无 onResolved,则自定义一个 onResolved函数,并传递成功结果if (typeof onResolved !== "function") {onResolve = value => value;}// 若无 onRejected,则自定义一个 onRejected函数,并传递失败结果if (typeof onRejected !== "function") {onRejected = (reason) =>{throw reason; // 抛出错误,这就是异常穿透,直到遇到 try...catch...才会停止。}}return new Promise((resolve, reject) => {// ...其他代码...})
}
当 then 中第二个参数 onRejected 回调函数为 undefined 时,给他一个自定义函数,然后一直抛出错误,让错误可以一直向下传递,直到遇到try...catch...
捕获错误,这种通过多层级获取抛出错误的方式就是异常穿透。
下图为上面代码的图示理解,我尽力了。
下一篇:云监控能力介绍