敞开生长之旅!这是我参与「日新计划 12 月更文应战」的第20天,点击查看活动概况第26篇文
Promise根底
一、Promise定义
Promise:许诺者形式:它是ES6新增的一个内置类,基于Promise能够有效管理”异步编程”,避免回调地狱
语法
executor函数
-
letp=newPromise([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
三、怎么改状况
- newPromise的时分,会立即把传递进来的executor[许诺履行人]函数履行,并且会给executor传递两个实参进来
咱们会用两个形参变量接纳resolve/reject,并且值是两个函数
- 当咱们履行resolve,promise实例状况变为fulfilled成功,传递的值便是成功的成果,赋值给[[PromiseResult]];
同理,只需把reject履行,promise实例状况变为rejected失利,传递的值便是失利的原因!
- 假如executor函数履行报错了,则实例的状况也是rejected失利,失利原因是便是错误信息!
newPromise发生的实例,他的状况是成功仍是失利,取决于“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 newPromise发生的是实例 &履行then办法回来的实例
-
newPromise发生的实例,他的状况是成功仍是失利,取决于“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
});