Promise的状态
Promise
有三个状态:
pending
:[待定]初始状态fulfilled
:[实现]操作成功rejected
:[被否决]操作失败
当promise
状态发生改变,就会触发then()
里的响应函数处理后续步骤。
promise
状态一经改变,不会再变。
Promise
对象的状态改变,只有两种可能:
- 从
pending
变为fulfilled
。 - 从
pending
变为rejected
。
这两种情况只要发生,状态就凝固了,不会再变了。
基本使用
知识点
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| let p = new Promise((res, rej) => { let t = new Date(), s = t.getSeconds(); if(s % 2) { res(s); }else{ rej(s, "参数二"); } });
# 调用方式1 p.then(res => console.log(res, "成功")) .catch(err => console.log(err, "失败")); # 调用方式2 p.then( res => console.log(res, "成功"), err => console.log(err, "失败") );
|
这里的rej
回调可以放在catch
(调用方式1),也可以放在then
的第二个参数(调用方式2)。
当然如果两个同时使用(调用方式3),只会执行放在.then
的第二个参数的函数,catch
内的函数不会执行。
通常都是使用调用方式1的用法。
奇怪的想法
返回多个参数会怎么样?
1 2 3 4 5 6 7 8 9 10 11 12 13
| let p = new Promise((res, rej) => { let t = new Date(), s = t.getSeconds(); if(s % 2) { res(s, "参数二"); }else{ rej(s, "失败参数2"); } });
p.then((res, res2) => console.log(res, res2, "成功")) .catch((err, err2) => console.log(err, err2, "失败"));
|
小结:假如向res
或者rej
函数中传入两个以上的参数,在响应函数当中只能取到第一个参数。
假如.then()
上面两种调用方式结合在一起会怎么样?
1 2 3 4 5 6 7
|
p.then( (res, res2) => console.log(res, res2, "成功"), (err, err2) => console.log(err, err2, "失败") ) .catch(err => console.log(err, "失败2"));
|
小结:Promise
在rejected
状态下,.then()
内有第二个参数,并且后续紧跟.catch()
。只会执行.then()
内第二个参数的响应函数。
链式调用
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
| function getImage(imgSrc) { return new Promise((res, rej) => { let img = new Image(); img.onload = function () { res(img.src); }
img.onerror = function () { rej(`图片加载失败:${imgSrc}`); }
img.src = imgSrc; }); }
getImage("image/1.png") .then(src => { console.log(src); return getImage("image/2.png"); }) .then(src => { console.log(src); return getImage("image/3.png"); }) .then(src => { console.log(src); }) .catch(err => console.log(err));
|
通过返回一个Promise
实例来实现链式调用。(使用方式跟原理有点像jQuery)
在上面代码中,假如有其中一张图片不存在,那么就会直接跑catch
内的函数。
当1.png这个图片不存在,却还想继续加载图片时,可以改写成这样。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| getImage("image/4.png") .then(src => { console.log(src); return getImage("image/4.png"); }, err => { console.log(err); return getImage("image/4.png"); }) .then(src => { console.log(src); return getImage("image/5.png"); }, err => { console.log(err); return getImage("image/6.png"); }) .then(src => { console.log(src); }) .catch(err => console.log(err));
|
使用调用方式2去接收错误错误,并且返回Promise
实例。让后续请求继续执行。
大概结构如下:
1 2 3 4 5 6 7 8 9 10 11 12
| promise对象 .then(成功回调, 失败回调) .then(成功回调, 失败回调) .then(成功回调, 失败回调)
promise对象 .then(成功回调, 失败回调) .then(成功回调, 失败回调) .then(成功回调) .catch(失败回调)
|
奇怪的想法
假如链式调用中不返回Promise
对象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| getImage("image/1.png") .then(src => console.log(src)) .then(src => console.log(src)) .then(src => console.log(src)) .catch(err => console.log(err));
getImage("image/不存在的.png") .then( src => console.log(src), err => console.log(err) ) .then( src => { console.log(src); return 666; }, err => console.log(err) ) .then( src => console.log(src), err => console.log(err) );
|
小结:不返回Promise
的时候,后续.then()
的响应函数也会继续执行。只不过返回给响应函数的返回值是根据上一个.then
中的返回值来决定的。
也就说明了.then()
会返回一个Promise
实例,所以他可以继续进行链式调用。
且这个实例的状态是fulfilled
成功的。
.then()
跟.catch()
中,假如没有返回Promise
实例
- 会自动返回一个状态为
fulfilled
的Promise
实例 - 且马上执行后面的
.then()
- 后面
.then()
中参数的值,上一个.then()
函数的返回值。
.then()
跟.catch()
中,假如返回Promise
实例
- 会根据返回的
Promise
实例状态,去执行对应的响应函数
抛出异常会怎么样
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| getImage("image/1.png") .then(src => { console.log(src); throw new Error("err"); }) .then(res => console.log(res)) .catch(err => console.log(err)) .then(res => { console.log(res); throw new Error("err2"); }) .then( res => console.log(res), err => console.log(err) ) .catch(err => console.log(err));
|
小结:上面代码中,抛出异常都会走到最近的reject
响应函数当中,并且跳过他们之间的.then()
响应函数。
参考链接:https://www.jianshu.com/p/1b63a13c2701