没有经过测试,其实我不太清楚如果一个 Promise 后加了多个 then、catch、finally 时候的处理逻辑。测试一下,可以帮助我们很好的去除误解,了解程序真正的执行逻辑。
测试代码
一、测试一
一个基础的 Promise
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| function testPromise() { return new Promise((resolve, reject) => { setTimeout(() => { resolve("成功!"); }, 1000); setTimeout(() => { reject("失败!"); }, 3000); }) .then((res) => { console.log("then:", res); return "then return"; }) .catch((err) => { console.log("catch:", err); return "catch return"; }) .finally((res) => { console.log("finally", res); return "finally return"; }); } testPromise();
|
- 一个 promise 中,resolve 和 reject 只会执行最先触发的一个
二、测试二
多次添加then
、catch
、finally
方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
| function testPromise() { return new Promise((resolve, reject) => { resolve("成功!"); }) .then((res) => { console.log("then 1:", res); return "then 1 return"; }) .catch((err) => { console.log("catch 1:", err); return "catch 1 return"; }) .finally((res) => { console.log("finally 1", res); return "finally 1 return"; }) .then((res) => { console.log("then 2:", res); return "then 2 return"; }) .catch((err) => { console.log("catch 2:", err); return "catch 2 return"; }) .finally((res) => { console.log("finally 2", res); return "finally 2 return"; }) .then((res) => { console.log("then 3:", res); return "then 3 return"; }) .catch((err) => { console.log("catch 3:", err); return "catch 3 return"; }) .finally((res) => { console.log("finally 3", res); return "finally 3 return"; }); } testPromise();
|
运行结果
- 第一个 then 的参数是 resolve 的参数值,然后执行第一个 finally
- 第二个 then 的回调参数是第一个 then 的返回值,然后执行第二个 finally,以此类推
- finally 无参数
三、测试三
抛出错误
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
| function testPromise() { return new Promise((resolve, reject) => { reject("失败!"); }) .then((res) => { console.log("then 1:", res); return "then 1 return"; }) .catch((err) => { console.log("catch 1:", err); return "catch 1 return"; }) .finally((res) => { console.log("finally 1", res); return "finally 1 return"; }) .then((res) => { console.log("then 2:", res); return "then 2 return"; }) .catch((err) => { console.log("catch 2:", err); return "catch 2 return"; }) .finally((res) => { console.log("finally 2", res); return "finally 2 return"; }) .then((res) => { console.log("then 3:", res); return "then 3 return"; }) .catch((err) => { console.log("catch 3:", err); return "catch 3 return"; }) .finally((res) => { console.log("finally 3", res); return "finally 3 return"; }); } testPromise();
|
- reject 抛出的错误会在第一个 catch 中捕获,参数是 reject 的参数值,接着执行第一个 finally
- 继续会执行第二个 then,参数是第一个 catch 的返回值,然后执行第二个 finally,接下来与上个测试类似,以此类推
四、测试四
- 在 resolve 后抛出错误
- 在第一个 then 中抛出错误
- 在第一个 catch 中抛出错误
- 在第二个 finally 中抛出错误
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
| function testPromise() { return new Promise((resolve, reject) => { resolve("成功!"); }) .then((res) => { console.log("then 1:", res); throw new Error("then 1 throw"); }) .catch((err) => { console.log("catch 1:", err); throw new Error("catch 1 throw"); }) .finally((res) => { console.log("finally 1", res); return "finally 1 return"; }) .then((res) => { console.log("then 2:", res); return "then 2 return"; }) .catch((err) => { console.log("catch 2:", err); return "catch 2 return"; }) .finally((res) => { console.log("finally 2", res); throw new Error("finally 2 throw"); }) .then((res) => { console.log("then 3:", res); return "then 3 return"; }) .catch((err) => { console.log("catch 3:", err); return "catch 3 return"; }) .finally((res) => { console.log("finally 3", res); return "finally 3 return"; }); } testPromise();
|
- 在 resolve 后,抛出错误不会被处理,与 reject 处理相似
- 在第一个 then 中抛出错误,被后续的第一个 catch(catch1)捕获,参数是错误值,后续继续执行。
- 在第一个 catch 中抛出错误,被后续的第一个 catch(catch2)捕获,参数是错误值,后续继续执行。
- 在第二个 finally 中抛出错误,被后续的第一个 catch(catch3)捕获,参数是错误值,后续继续执行。
五、测试五
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| function testPromise() { const a = new Promise((resolve, reject) => { resolve("成功!"); }); const b = a.finally((res) => { console.log("finally 1", res); return "finally 1 return"; }); const c = a.then((res) => { console.log("then 1:", res); throw new Error("then 1 throw"); }); const d = a.catch((err) => { console.log("catch 1:", err); throw new Error("catch 1 throw"); }); const e = a.catch((err) => { console.log("catch 2:", err); }); console.log("a === b", a === b); console.log("a === c", a === c); console.log("a === d", a === d); } testPromise();
|
- then、finally、catch 返回的都是一个新的 Promise,所以 a、b、c、d、e 的值都是不同的
- 在 a 上添加的 catch 仅会处理 a 的 reject 和错误,不会处理 then 和 finally 的错误
- then、finally 执行是按照事件添加顺序
六、测试六
分别在 a 和 a.then 上添加 then、catch、finally
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
| function testPromise() { const a = new Promise((resolve, reject) => { resolve("成功!"); }); const b = a.then((res) => { console.log("then 1:", res); return "then 1 return"; }); a.catch((err) => { console.log("catch 1:", err); return "catch 1 return"; }); a.finally((res) => { console.log("finally 1", res); return "finally 1 return"; }); b.then((res) => { console.log("then 2:", res); return "then 2 return"; }); b.catch((err) => { console.log("catch 2:", err); return "catch 2 return"; }); b.finally((res) => { console.log("finally 2", res); return "finally 2 return"; }); a.then((res) => { console.log("then 3:", res); return "then 3 return"; }); a.catch((err) => { console.log("catch 3:", err); return "catch 3 return"; }); a.finally((res) => { console.log("finally 3", res); return "finally 3 return"; }); } testPromise();
|
- 将 a.then 的返回值保存为 b,可以看到 b 上添加的 then、catch、finally 执行必然在 a 上添加的 then、catch、finally 之后执行
- 在同一个 Promise 对象上多次添加 then、catch、finally,也会按照添加顺序依次执行
总结
为了方便,以下内容中“三个方法”指 then、catch、finally 方法
- 一个 Promise 中,resolve 和 reject 只会执行最先触发的一个
- Promise 对象的三个方法都会返回一个 新的 Promise 对象
- 因为三个方法都会返回 Promise 对象,且返回值和错误都会向后传递,所以可以链式调用。比如 Promise 链靠前的方法中抛出错误,会被后续 Promise 对象的 catch 方法捕获。
- 在三个方法中 return 值,会作为后续的第一个 then 方法的参数
- 在三个方法中 throw 值,会被后续的第一个 catch 方法捕获。如果在这个 catch 方法中没有继续抛出错误,则不会被后续的 catch 方法捕获
- 在同一个 Promise 对象上,多次添加 then、finally 方法,均会被执行,且会 按照添加顺序依次执行
- 在同一个 Promise 对象上,多次添加 catch 方法,仅会被第一个添加的 catch 方法捕获
- 在 Promise 对象的三个方法 返回的 Promise 对象 上添加的三个方法,必然会 在原 Promise 对象 上添加的三个方法 之后执行
- 在一个 Promise 链上,多次添加 then、catch、finally 也会按照添加顺序依次执行。