Promise基础
Promise基础
一、Promise定义
Promise:承诺者模式:它是ES6新增的一个内置类,基于Promise可以有效管理"异步编程",避免回调地狱
语法
executor函数
-
let p=new Promise([executor]) 语法
-
p是它的实例
-
[executor]是一个函数,传递的不是函数会报错
-
p.proto===Promise.prototype[所属类的原型]
-
实例私有属性
-
[[PromiseState]]:"pending"
-
promise实例的状态有三种
-
pending准备状态
-
fulfilled/resolved成功状态
-
rejected失败状态
-
-
最初的状态是pending,后期基于某些操作可以把状态改变为fulfilled或者rejected
-
(但是一但状态变为成功或者失败,则再也不能修改其状态了)
-
-
[[PromiseResult]]:undefined
- [[PromiseResult]]存放的是成功的结果或者失败的原因!
-
-
实例公有属性
then / catch / finally / Symbol.toStringTag="Promise" [原型上]
二、状态改完有什么用
-
基于then可以存放两个函数 p.then(onfulfilled,onrejected)
-
当我们把状态修改为fulfilled成功态,则会把onfulfilled这个函数执行,相反,我们把状态修改为rejected失败态,则会把onrejected这个函数执行...
-
并且会把[[PromiseResult]]作为实参值,传递给onfulfilled/onrejected
三、怎么改状态
- new Promise的时候,会立即把传递进来的executor[承诺执行人]函数执行,并且会给executor传递两个实参进来
我们会用两个形参变量接收resolve/reject,并且值是两个函数
- 当我们执行resolve,promise实例状态变为fulfilled成功,传递的值就是成功的结果,赋值给[[PromiseResult]];
同理,只要把reject执行,promise实例状态变为rejected失败,传递的值就是失败的原因!
- 如果executor函数执行报错了,则实例的状态也是rejected失败,失败原因是就是错误信息!
new Promise产生的实例,他的状态是成功还是失败,取决于“resolve/reject执行 或者 executor执行是否报错”
//========================>基础语法
let p=new Promise(function exector(resolve,reject){
console.log(1);//先输出1
resolve('OK');//promise实例状态变为fulfilled
});
console.log(p);
//p.then(onfulfilled,onrejected)
p.then(function onfulfilled(result){
//当状态为fulfilled的时候 会执行此函数
//result 存放的是成功结果 OK
},function onrejected(reason){
//当状态为rejected的时候,会执行此函数
//reason 失败的原因
});
四、Promise的then
new Promise((resolve, reject) => {
$.ajax({
url: './api/data1.json',
success(result) {
resolve(result); //成功的时候把=》实例状态成功
},
error(reason) {
reject(reason);
}
});
}).then(result => {
console.log('请求成功', result);//成功做什么
}, reason => {
console.log('请求失败', reason);//失败做什么
});
//========================setTimeout异步
new Promise((resolve, reject) => {
setTimeout(() => {
let ran = Math.random();
if (ran > 0.5) resolve('OK');
reject('NO');
}, 1000);
}).then(result => {
console.log('请求成功', result);
}, reason => {
console.log('请求失败', reason);
});
4.1 多次.then
我们可以基于 “promise实例.then” 存放多个onfulfilled/onrejected方法,状态变为成功或者失败,
存放的每一个对应的方法都会被执行
let p1 = new Promise((resolve, reject) => {
resolve(100);//实例状态变为成功
});
p1.then(result => {
console.log(`成功:${result}`);//输出成功,100
}, reason => {
console.log(`失败:${reason}`);
});
p1.then(result => {
console.log(`成功:${result}`);//输出成功,100
}, reason => {
console.log(`失败:${reason}`);
});
4.2 new Promise产生的是实例 &执行then方法返回的实例
-
new Promise产生的实例,他的状态是成功还是失败,取决于“resolve/reject执行 或者 executor执行是否报错”
-
每一次执行THEN方法,不仅存放了onfulfilled/onrejected方法,而且还会返回一个“全新的promise实例”
-
新实例p2的状态和值由谁来决定呢?
-
首先看返回值是否是一个新的Promise实例
-
不论onfulfilled/onrejected这两个方法执行的是哪一个,我们只看执行是否报错;
-
如果报错,则p2的状态是失败态rejected,值是报错原因!
-
如果不报错,则p2的状态是成功态fulfilled,值是函数的返回值!
-
-
-
let p1 = new Promise((resolve, reject) => {
reject(0);
});
let p2 = p1.then(result => {
console.log(`成功:${result}`);
return 1000;
}, reason => {
console.log(`失败:${reason}`); //失败 0 //没有报错代码 所以新实例的状态为成功
return -1000;
});
let p3 = p2.then(result => {
console.log(`成功:${result}`); //成功 -1000
throw new Error('xxx');//因为有错误信息,所以这个返回的实例是失败状态
}, reason => {
console.log(`失败:${reason}`);
});
p3.then(result => {
console.log(`成功:${result}`);
}, reason => {
console.log(`失败:${reason}`); //失败 Error:xxx //失败就会执行reason
});
4.3 .then 返回值是一个新的promise实例的特殊情况
特殊情况:我们之前说,不论onfulfilled/onrejected执行,只要不报错,则新实例p2的状态就是成功,只要报错就是失败...但是这里有一个特殊的情况:“执行不报错,但是返回值是一个新的promise实例,这样返回值的这个promise实例是成功还是失败,直接决定了p2是成功还是失败”
let p1 = new Promise((resolve, reject) => {
resolve(100);
});
let p2 = p1.then(result => {
console.log(`成功:${result}`); //成功 100
return new Promise((resolve, reject) => reject(-1000)); //执行了reject 所以状态为失败
}, reason => {
console.log(`失败:${reason}`);
return -1000;
});
p2.then(result => {
console.log(`成功:${result}`);
}, reason => {
console.log(`失败:${reason}`); //失败:-1000
});
let p1 = new Promise((resolve, reject) => {
reject(0);//执行了失败的方法
});
let p2 = p1.then(result => {
console.log(`成功:${result}`);
return new Promise((resolve, reject) => reject(-1000));
}, reason => {
console.log(`失败:${reason}`); //失败:0 //p1执行的是reject
return new Promise((resolve, reject) => resolve(1000)); //成功
});
p2.then(result => {
console.log(`成功:${result}`); //成功:1000
}, reason => {
console.log(`失败:${reason}`);
});
五、Promise的then链机制
Promise中的then链机制:因为每一次.then都会返回一个新的promise实例,所以我们就可以持续.then下去了
而且因为实例诞生的方式不同,所以状态判断标准也不同
第一类 : new Promise 出来的实例
- 执行的是 resolve 还是 reject 决定状态
- executor函数执行是否报错
第二类 :. then 返回的新实例
.then执行会返回一个全新的promise实例“p2”:不论是then中的onfulfilled还是onrejected执行
-
首先看返回值是否为新的promise实例,
-
如果返回的是新的promise实例,则新的promise实例的状态和值,直接决定了.then返回的实例的状态和值
-
如果不是,则只看执行是否报错「不报错状态就是成功,值就是函数返回值;报错则状态就是失败,值就是失败原因」
-
第三类 :把Promise当做对象
-
Promise.resolve(100) 返回一个状态是成功,值是100的新promise实例【值就是你传递实参进来的实参信息】
-
Promise.reject(0) 返回一个状态是失败,值是0的新promise实例
只要实例的状态和值我们分析好,则 .then(onfulfilled,onrejected) 存放的方法,哪一个执行我们就知道了
let p1 = new Promise((resolve, reject) => {
resolve(1);//更改p1的状态
reject(0);
});
let p2 = p1.then(function onfulfilled(result) {
//执行onfulfilled =>没有报错 没有返回值 则p2的状态是成功 值是undefined
}, function onrejected(reason) {
});
p2.then(function onfulfilled(result) {
console.log(result);//结果是undefined
}, function onrejected(reason) {
});
思考题
Promise.resolve(100).then(result => {
console.log(`成功:${result}`);//100
return result / 10;
}, reason => {
console.log(`失败:${reason}`);
return Promise.resolve(200);
}).then(result => {
console.log(`成功:${result}`);//10
return Promise.reject(300);
}, reason => {
console.log(`失败:${reason}`);
return reason / 20;
}).then(result => {
console.log(`成功:${result}`);
return 0;
}, reason => {
console.log(`失败:${reason}`);//300
return 1;
}).then(result => {
console.log(`成功:${result}`);//成功1
}, reason => {
console.log(`失败:${reason}`);
});
Promise.resolve(Promise.reject(100)); //传递的值是失败的promise实例
// 状态:fulfilled
// 值:新的实例 -> 状态:rejected 值:100 */
Promise.resolve(10).then(result => {
console.log(`成功:${result}`); //成功 10
return Promise.resolve(Promise.reject(100));
//如果实例的状态是成功状态,需要把它的值再次处理一遍,以最后一个值处理的结果为准
}).then(result => {
console.log(`成功:${result}`);
}, reason => {
console.log(`失败:${reason}`); //失败:100
});
//===========================
Promise.resolve(10).then(result => {
console.log(`成功:${result}`); //成功:10
return Promise.reject(Promise.resolve(100));
}).then(result => {
console.log(`成功:${result}`);
}, reason => {
console.log(`失败:${reason}`); //失败:[object Promise]
});
以上总结:如果执行onfulfilled或者onrejected的时候,返回的值是是一个promise实例“@P”,
我们之前说“@P”是成功还是失败,直接决定了“p2(.then返回的新实例)”是成功还是失败...但是这样是不严谨的,
-
按照官方规范要求:
-
如果@P是成功状态,需要把它的值再次处理一遍...
-
如果@P是失败的,直接认定为失败的状态,不需要把失败的值再次处理...
-
5.1 then链的穿透性(顺延)
正常情况下,.then的时候会传递两个函数onfulfilled/onrejected,但是有些时候,我们是不传递其中的某个函数的,这种情况下我们需要采取“顺延策略”:找到下一个then中对应状态的函数执行
例如:.then(null,onrejected) 【只处理失败】或者 .then(onfulfilled)【只处理成功】
Promise.reject(0).then(result => {
console.log(`成功:${result}`);
return 1;
}).then(result => {
console.log(`成功:${result}`);
return 2;
}).then(result => {
console.log(`成功:${result}`);
return 3;
}, reason => {
console.log(`失败:${reason}`); //失败:0
});
//==================
Promise.resolve(100).then(result => {
console.log(`成功:${result}`); //成功:100
throw '我失败了'; //自己抛出异常
}).then(result => {
console.log(`成功:${result}`);
return 2;
}).then(result => {
console.log(`成功:${result}`);
return 3;
}, reason => {
console.log(`失败:${reason}`); //失败:我失败了 顺延至最后一个reason
});
//======================
Promise.resolve(100).then(result => {
console.log(`成功:${result}`); //成功:100
return 1;
}).then(result => {
console.log(`成功:${result}`); //成功:1
return Promise.reject('NO');
}).then(null, reason => {
console.log(`失败:${reason}`); //失败:NO
});
5.2 Promise.catch
.catch(onrejected) 相当于==> .then(null,onrejected)
真实项目中,我们经常:then中只传递onfulfilled,处理状态是成功的事情;在then链的末尾设置一个catch,处理失败的事情(依托于then链的穿透机制,无论最开始还是哪个then中,出现了让状态为失败的情况,都会顺延到最末尾的catch部分进行处理)
Promise.resolve(100).then(result => {
console.log(`成功:${result}`); //成功:100
return 1;
}).then(result => {
console.log(`成功:${result}`); //成功:1
return Promise.reject('NO');
}).catch(reason => {
console.log(`失败:${reason}`); //失败:NO
});
转载自:https://juejin.cn/post/7177731524962287673