一、什么是Promise:
-
Promise 是在 js 中进行异步编程的新解决方案。(以前旧的方案是单纯使用回调函数)
-
从语法来说,promise是一个构造函数。
-
从功能来说,promise对象用来封装一个异步操作,并且可以获得成功或失败的返回值。
-
JS中的常见的异步操作:定时器、数据库操作,fs文件操作,AJAX中一般也是异步操作(也可以同步),回调函数可以理解为异步(不是严谨的异步操作)…等。剩下的都是同步处理
二、为啥使用Promise
- promise使用回调函数更灵活。旧的回调函数必须在启动异步任务前指定。
- promise:启动异步任务 => 返回promise对象 => 给promise对象绑定回调函数(甚至能在异步任务结束后指定多个)
- promise
支持链式调用
,可以解决回调地狱问题
。(回调地狱就是多层回调函数嵌套使用,就是套娃,这样就不利于阅读和异常处理。)
三、promise初体验:
效果:点击一个按钮,有30%概率显示中奖。
实现: 点击按钮后得到一个1到100间的随机数,小于等于30输出中奖,否则输出没中。期间用定时器模拟异步操作,在定时器里执行判断。
(1)基础的写法:
<button id="btn">click</button>
<script>
var btn = document.querySelector("#btn");
// 该函数返回一个两数之间的随机整数,包括两个数在内
function getRandomIntInclusive(min, max) {
min = Math.ceil(min);
max = Math.floor(max);
return Math.floor(Math.random() * (max - min + 1)) + min; //含最大值,含最小值
}
// 点击事件
btn.addEventListener('click',function(){
// 1秒的定时器,模拟异步操作
setTimeout(() => {
// 得到1到100间的一个数
let n = getRandomIntInclusive(1, 100);
if (n <= 30) {
alert('中奖喽');
} else {
alert('没中奖');
}
}, 1000);
})
</script>
(2)promise写法,在promise里封装一个异步操作。
<script>
var btn = document.querySelector("#btn");
// 得到一个两数之间的随机整数,包括两个数在内
function getRandomIntInclusive(min, max) {
min = Math.ceil(min);
max = Math.floor(max);
return Math.floor(Math.random() * (max - min + 1)) + min; //含最大值,含最小值
}
// 点击事件
btn.addEventListener('click',function(){
// 下面是promise ,resolve表示解决,reject表示拒绝 ,都是函数类型数据。
const p = new Promise((resolve,reject) => {
setTimeout(()=>{
let n = getRandomIntInclusive(1, 100);
if(n<=30){
resolve(); //将promise状态设为 “成功”
}else{
reject(); //将promise状态设为 “失败”
}
},1000)
});
// 调用then方法
p.then(()=>{
// “成功”执行这步
alert('中奖喽');
},()=>{
// “失败”执行这步
alert('没中奖');
})
})
假如要在上面输出结果后加上选中的号码:
因为.then()里并不能直接获得 n,所以在resolve与reject里把n当结果值返回。
// 点击事件
btn.addEventListener('click',function(){
// 下面是promise ,resolve表示解决,reject表示拒绝 ,都是函数类型数据。
const p = new Promise((resolve,reject) => {
setTimeout(()=>{
let n = getRandomIntInclusive(1, 100);
if(n<=30){
resolve(n); //将promise状态设为 “成功”,并把结果值n返回
}else{
reject(n); //将promise状态设为 “失败”,并把结果值n返回
}
},1000)
});
// 调用then方法
// value为值的意思,reason为理由的意思,都是形参
p.then((value)=>{
// “成功”执行
alert(`中奖喽+${value}`);
},(reason)=>{
// “失败”执行
alert('没中奖'+reason);
})
})
四、promise体验Ajax请求
这是一个开源社区的api文档,有许多api。
效果:点击按钮获得一句名言在控制台输出。
基础写法:
<script>
var btn = document.querySelector("#btn");
// 点击事件
btn.addEventListener('click',function(){
//创建对象
const xhr = new XMLHttpRequest();
//初始化
xhr.open('GET',"http://poetry.apiopen.top/sentences");
//发送
xhr.send();
//处理响应结果
xhr.onreadystatechange = function(){
if(xhr.readyState === 4){
if(xhr.status >=200 && xhr.status < 300){
//输出响应体
console.log(xhr.response);
}else{
//输出响应状态码
console.log(xhr.status);
}
}
}
})
</script>
promise封装:
// 点击事件
btn.addEventListener('click',function(){
const p = new Promise((resolve,reject) => {
//创建对象
const xhr = new XMLHttpRequest();
//初始化
xhr.open('GET', "http://poetry.apiopen.top/sentences");
//发送
xhr.send();
//处理响应结果
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
if (xhr.status >= 200 && xhr.status < 300) {
//输出响应体
resolve(xhr.response);
} else {
//输出响应状态码
reject(xhr.status);
}
}
}
})
p.then(value=>{
console.log(value);
},reason=>{
//控制台输出警告信息
console.warn(reason);
})
})
若把接口写错:
五、Promise封装AJAX请求
跟上一步差不多。就是把其封装在一个sendAJAX()的自定义函数里。
function sendAJAX(url) {
return new Promise((resolve, reject) => {
//创建对象
const xhr = new XMLHttpRequest();
xhr.responseType = 'json';
//初始化
xhr.open('GET', url);
//发送
xhr.send();
//处理响应结果
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
if (xhr.status >= 200 && xhr.status < 300) {
//输出响应体
resolve(xhr.response);//promise状态变为fulfilled
} else {
//输出响应状态码
reject(xhr.status); //promise状态变为rejected
}
}
}
});
}
// 返回的就是promise对象
// console.log(sendAJAX("http://poetry.apiopen.top/sentences"))
sendAJAX("http://poetry.apiopen.top/sentences")
.then(value=>{
console.log(value);
},reason=>{
//控制台输出警告信息
console.warn(reason);
})
// 这样分开写也可以
// .then(value=>{
// console.log(value);
// }).catch(error=>{
// console.log(error);
// })
六、promise的状态改变
promise状态表示实例对象的一个属性【PromiseState】。包括以下值:
(1)pending 未决定的
(2)resolved 或 fullfilled 成功
(3)rejected 失败
Promise对象的值表示实例对象的另一个属性【PromiseResult】。保存着对象【成功/失败】的结果。而其状态改变只有以下两种可能:
(1)pending 变为resolved( fullfilled)//调用resolve()
(2)pending 变为 rejected //调用reject()
注:一个promise对象只能改变一次
,无论成功或失败都会有一个结果数据,成功的称为 value , 失败的称为 reason 。
七、Promise基本流程图:
执行then()方法返回的也是一个promise,所以可以链式调用
八、Promise的API使用:
1.Promise 的构造函数:Promise(executor){}
(1)executor 函数:执行器 (resolve,reject)=> {}。
(2)resolve 函数:内部定义成功时调用函数 value => {} 。
(3)reject 函数:内部定义失败时调用函数 reason => {} 。
注意:Promise内部会立即同步调用executor,异步操作在执行器里执行。
<script>
let p = new Promise((resolve, reject) => {
// 同步调用
console.log(1);
})
console.log(2);
</script>
2.Promise.prototype.then 方法: (onResolved, onRejected)=> {}
(1) onResolved 函数:成功的回调函数 (value) => {}
(2) onRejected 函数:失败的回调函数 (reason) => {}
注:指定用于得到成功value的成功回调和用于得到失败reason的失败回调是返回一个新的promise对象
。
3.Promise.prototype.catch方法: (onRejected) => {}
onRejected.函数: 失败的回调函数**(reason)=> {}**
注:只是失败的调用。then()的语法糖,相当于: then(undefined, onRejected)。
let p = new Promise((resolve, reject) => {
reject('error')
})
p.catch(reason=>{
console.log(reason);
})
4.Promise.resolve 方法: (value)=> {}(函数对象的方法)
value: 成功的数据或promise对象
注:如果传入的参数为非Promise类 型的对象,则返回的结果为成功promise对象,如果传入的参数为Promise 对象,则参数的结果决定了resolve 的结果。
let p1 = Promise.resolve(521);
console.log(p1);
let p2 = Promise.resolve(new Promise((resolve, reject) => {
// resolve('成功')
reject('失败')
}))
console.log(p2);
// reject调用后 的报错处理
p2.catch(reason => {
console.log(reason);
})
resolve(‘成功’):
reject(‘失败):
5.Promise.reject 方法: (reason) => {} (函数对象的方法)
reason: 失败的原因
注:无论传入啥只返回一个失败的promise对象。
let p = Promise.reject(521)
let p2 = Promise.reject(new Promise((resolve,reject)=>{
resolve('失败的promise')
}))
console.log(p);
console.log(p2);
p.catch(reason=>{
console.log(reason);
});
p2.catch(reason=>{
console.log(reason);
});
6.Promise.all 方法: (promises)=> {}
promises: 包含n个promise的数组
注:返回一个新的promise,只有所有的promise都成功才成功,只要有一个失败了就直接失败。失败了返回那个失败值。
let p1 = new Promise((resolve, reject) => {
resolve('success')
})
let p2 = Promise.resolve('OK');
// let p2 = Promise.reject('error')
let p3 = Promise.resolve('Yeah')
const result = Promise.all([p1, p2, p3])
console.log(result); // 成功的promise对象,结果值就是三个promise它们成功的结果组成的数组
result.then(value => {
console.log(value);
}, reason => {
console.log(reason);
})
所有promise都成功时的返回:
其中存在失败的promise时的返回:
7.Promise.race方法:(promises)=>{}
promises: 包含n个promise的数组
注:返回一个新的promise,第一个完成的promise
的结果状态就是最终的结果状态。
race就是比赛的意思
来一个例子:
let p1 = new Promise((resolve,reject)=>{
setTimeout(()=>{
resolve('yes');
},1000)
})
let p2 = Promise.resolve('success');
let p3 = Promise.resolve('come');
const result = Promise.race([p1,p2,p3]);
console.log(result);
九、使用Promise面临的关键问题:
1.如何改变 promise的状态?
(1) resolve(value): 如果当前是pending就会变为(fulfilled)resolved。
(2) reject(reason): 如果当前是pending就会变为rejected。
(3)抛出异常 throw :如果当前是pending就会变为rejected。
let p1 = new Promise((resolve,reject)=>{
// resolve('success');
// reject('error');
throw 'error'; // 或者抛出异常对象也可以
})
console.log(p1);
p1.catch(reason=>{
console.log(reason);
})
2. 一个 promise指定多个成功/失败回调函数,都会调用吗?
当promise改变为对应状态时都会调用。
let p = new Promise((resolve,reject)=>{
resolve('success'); // 这个不执行p的状态就不会改变,下面的回调函数就不会调用
})
// 第一次回调
p.then(value=>{
console.log("yes");
alert(value); // success
})
// 第二次回调
p.then(value=>{
console.log("oh yes");
alert(value); // success
})
3.改变 promise状态和指定回调函数谁先谁后?
指定回调-改变状态-执行回调
是指定回调先呢?还是改变状态先呢?
(1)都有可能, 正常情况下是先指定回调再改变状态,但也可以先改状态再指定回调
(2)如何先改状态再指定回调?
①在执行 器中直接调用resolve(/reject();
②延迟更 长时间才调用then();
(3)什么时候才能得到数据?
①如果先指定的回调, 那当状态发生改变时,回调函数就会调用,得到数据
②如果先改变的状态, 那当指定回调时,回调函数就会调用,得到数据
4.promise.then()返回新的promise的结果状态由什么决定?
(1)简单表达: then()指定的回调函数执行的结果决定。
(2)详细表达:
*如果抛出异常, 新promise变为rejected, reaon为抛出的异常。
*如果返回的是非prormise的任意值,新promise变为resolved, value为返回的值。
*如果返回的是另一个新promise,此promise的结果就会成为新promise的结果。
let p = new Promise((resolve, reject) => {
resolve('success');
// reject('No');
// throw 'oh no';
});
let result = p.then(value => {
//console.log(value); // fulilled undefined 这个等于return undefined
//return 123 //result 会变为fulfilled状态 promiseResult 为123
// throw 'error' //result 会变为失败状态 promiseResult 为error
// return Promise.reject('失败') // rejected '失败'
// return new Promise((resolve,reject)=>{
//reject(123) //rejected 123
//resolve(456) //fulfilled 456
})
//return Promise.resolve('成功') // fulfilled '成功'
}, reason => {
console.warn(reason);
});
console.log(result);
5.promise 如何串连多个操作任务?
(1) promise 的then()返回一个新的promise,可以看成then()的链式调用。
(2)通过then的链式调用串连多个同步/异步任务。
let p = new Promise((resolve, reject) => {
resolve("yes");
})
p.then(value => {
console.log(value);
return new Promise((resolve, reject) => {
resolve("oh yes~");
});
}).then(value => {
console.log(value); // on yes~ // 当前promise对象:fulfiled undefined
}).then(value=>{
console.log(value); // undefined
})
输出结果:
yes
oh yes~
undefined
6.promise 的异常穿透。
(1)当使用promise的then链式调用时,可以在最后指定失败的回调。
(2)前面任何操作出 了异常,都会传到最后失败的回调中处理。
let p =new Promise((resolve,reject) => {
setTimeout(()=>{
resolve("yes");
},1000);
})
p.then(value => { // 这里执行
throw 'oh No';
}).then(value => { // 这里不执行
console.log("123");
}).then(value => { //这里不执行
console.log("456");
}).catch(reason=>{ // 抛出异常后直接跳到这里
console.warn(reason);
})
输出结果:
oh No
let p = new Promise((resolve, reject) => {
setTimeout(() => {
resolve("yes");
}, 1000);
})
p.then(value => {
console.log(value); //yes
// throw 'oh No';
console.log('aa');
}).then(value => {
console.log(value); //undefined//上一个promise状态成功rusult:undefined
console.log("123");
}).then(value => {
console.log(value); // undefined
console.log("456");
}).catch(reason => {
console.warn(reason);
})
7.中断promise链
(1)当使用promise的then链式调用时,在中间中断,不再调用后面的回调函数。
(2)办法:在回调函数中返回一个pendding状态的promise对象。
未中断:
let p =new Promise((resolve,reject) => {
setTimeout(()=>{
resolve("yes");
},1000);
})
p.then(value => {
console.log("789");
}).then(value => {
console.log("123");
}).then(value => {
console.log("456");
}).catch(reason=>{
console.warn(reason);
})
输出结果:
789
123
456
中断:
let p =new Promise((resolve,reject) => {
setTimeout(()=>{
resolve("yes");
},1000);
})
p.then(value => {
console.log("789");
return new Promise(()=>{});//状态没有改变,后续回调不会执行
}).then(value => {
console.log("123");
}).then(value => {
console.log("456");
}).catch(reason=>{
console.warn(reason);
})
输出结果:
789
十、Promise的自定义封装
1.初始化解构搭建
// 自定义函数 Promise executor:执行器函数
function Promise(executor){
}
// 添加then方法
Promise.prototype.then = function(onResolved,onRejected){
}
注:prototype (原型对象)属性使您有能力向对象添加属性和方法。(这里涉及构造函数和原型链的知识)
2.搭建resolve与reject函数
// 自定义函数Promise
function Promise(executor){
//自定义resolve函数,名字不一定用resolve
function resolve(data){
}
//自定义reject函数
function reject(data){
}
//同步调用【执行器函数】
executor(resolve,reject);
}
// 添加then方法
Promise.prototype.then = function(onResolved,onRejected){
}
3.实现resolve与reject函数
// 自定义函数Promise
function Promise(executor){
//添加状态属性与结果值属性
this.PromiseState = 'pending';
this.PromiseResult = null;
//保存实例对象的this值
const that = this;
//自定义resolve函数,名字不一定用resolve
function resolve(data){
//改变状态属性
that.PromiseState = 'fulfilled'; // 或者 resolved
//改变结果值属性
that.PromiseResult =data;
}
//自定义reject函数
function reject(data){
//改变状态属性
that.PromiseState = 'rejected';
//改变结果值属性
that.PromiseResult =data;
}
//同步调用【执行器函数】
executor(resolve,reject);
}
// 添加then方法
Promise.prototype.then = function(onResolved,onRejected){
}
4.throw抛出异常改变状态
采用 try{ }catch(){ } 与throw一起使用。
// 自定义函数Promise
function Promise(executor){
//添加状态属性与结果值属性
this.PromiseState = 'pending';
this.PromiseResult = null;
//保存实例对象的this值
const that = this;
//自定义resolve函数,名字不一定用resolve
function resolve(data){
//改变状态属性
that.PromiseState = 'fulfilled'; // 或者 resolve
//改变结果值属性
that.PromiseResult =data;
}
//自定义reject函数
function reject(data){
//改变状态属性
that.PromiseState = 'rejected';
//改变结果值属性
that.PromiseResult =data;
}
try{
//同步调用【执行器函数】
executor(resolve,reject);
}catch(e){
//更改Promise对象为失败
reject(e);
}
}
// 添加then方法
Promise.prototype.then = function(onResolved,onRejected){
}
注:throw语句抛出一个错误。
5.设定Promise对象状态只能修改一次
加个判断就好。
// 自定义函数Promise
function Promise(executor){
//添加状态属性与结果值属性
this.PromiseState = 'pending';
this.PromiseResult = null;
//保存实例对象的this值
const that = this;
//自定义resolve函数,名字不一定用resolve
function resolve(data){
//判断状态是否修改过,改过就直接返回
if(that.PromiseState !== 'pending') return;
//改变状态属性
that.PromiseState = 'fulfilled'; // 或者 resolve
//改变结果值属性
that.PromiseResult =data;
}
//自定义reject函数
function reject(data){
//判断状态是否修改过,改过就直接返回
if(that.PromiseState !== 'pending') return;
//改变状态属性
that.PromiseState = 'rejected';
//改变结果值属性
that.PromiseResult =data;
}
try{
//同步调用【执行器函数】
executor(resolve,reject);
}catch(e){
//更改Promise对象为失败
reject(e);
}
}
// 添加then方法
Promise.prototype.then = function(onResolved,onRejected){
}
6. then()方法执行回调:
// 自定义函数Promise
function Promise(executor){
//添加状态属性与结果值属性
this.PromiseState = 'pending';
this.PromiseResult = null;
//保存实例对象的this值
const that = this;
//自定义resolve函数,名字不一定用resolve
function resolve(data){
//判断状态是否修改过
if(that.PromiseState !== 'pending') return;
//改变状态属性
that.PromiseState = 'fulfilled'; // 或者 resolve
//改变结果值属性
that.PromiseResult =data;
}
//自定义reject函数
function reject(data){
//判断状态是否修改过,改过就直接返回
if(that.PromiseState !== 'pending') return;
//改变状态属性
that.PromiseState = 'rejected';
//改变结果值属性
that.PromiseResult =data;
}
try{
//同步调用【执行器函数】
executor(resolve,reject);
}catch(e){
//更改Promise对象为失败
reject(e);
}
}
// 添加then方法
Promise.prototype.then = function(onResolved,onRejected){
//如果Promise状态为fulfilled回调这个函数
if(this.PromiseState === 'fulfilled'){
//将结果值传入
onResolved(this.PromiseResult);
}
//如果Promise状态为rejected回调这个函数
if(this.PromiseState === 'rejected'){
//将结果值传入
onRejected(this.PromiseResult);
}
}
7.执行异步任务回调:
异步任务一般先回调才改变状态。所以第6步的代码执行顺序就无法执行异步回调,解决如下:
// 自定义函数Promise
function Promise(executor){
//添加状态属性与结果值属性
this.PromiseState = 'pending';
this.PromiseResult = null;
// 定义callback属性,保存pending状态的回调函数
this.callback = {};
//保存实例对象的this值
const that = this;
//自定义resolve函数,名字不一定用resolve
function resolve(data){
//判断状态是否修改过
if(that.PromiseState !== 'pending') return;
//改变状态属性
that.PromiseState = 'fulfilled'; // 或者 resolve
//改变结果值属性
that.PromiseResult =data;
//异步任务成功后执行回调函数
if(that.callback.onResolved){
that.callback.onResolved(data);
}
}
//自定义reject函数
function reject(data){
//判断状态是否修改过,改过就直接返回
if(that.PromiseState !== 'pending') return;
//改变状态属性
that.PromiseState = 'rejected';
//改变结果值属性
that.PromiseResult =data;
//异步任务失败后执行回调函数
if(that.callback.onRejected){
that.callback.onRejected(data);
}
}
try{
//同步调用【执行器函数】
executor(resolve,reject);
}catch(e){
//更改Promise对象为失败
reject(e);
}
}
// 添加then方法
Promise.prototype.then = function(onResolved,onRejected){
//如果Promise状态为fulfilled回调这个函数
if(this.PromiseState === 'fulfilled'){
//将结果值传入
onResolved(this.PromiseResult);
}
//如果Promise状态为rejected回调这个函数
if(this.PromiseState === 'rejected'){
//将结果值传入
onRejected(this.PromiseResult);
}
//如果Promise状态为pending,保存回调函数
if(this.PromiseState === 'pending'){
this.callback = {
onResolved: onResolved,
onRejected: onRejected
}
}
}
8.能执行多个回调:
用第7步写法指定多个回调时,最后一个then回调会覆盖掉前面的,解决如下,把保存回调函数的callbacks变为一个数组:
// 自定义函数Promise
function Promise(executor){
//添加状态属性与结果值属性
this.PromiseState = 'pending';
this.PromiseResult = null;
// 定义callback属性,保存pending状态的回调函数
this.callbacks = [];
//保存实例对象的this值
const that = this;
//自定义resolve函数,名字不一定用resolve
function resolve(data){
//判断状态是否修改过
if(that.PromiseState !== 'pending') return;
//改变状态属性
that.PromiseState = 'fulfilled'; // 或者 resolve
//改变结果值属性
that.PromiseResult =data;
//异步任务成功后执行回调函数
that.callbacks.forEach(item=>{
item.onResolved(data);
})
}
//自定义reject函数
function reject(data){
//判断状态是否修改过,改过就直接返回
if(that.PromiseState !== 'pending') return;
//改变状态属性
that.PromiseState = 'rejected';
//改变结果值属性
that.PromiseResult =data;
//异步任务失败后执行回调函数
that.callbacks.forEach(item=>{
item.onRejected(data);
})
}
try{
//同步调用【执行器函数】
executor(resolve,reject);
}catch(e){
//更改Promise对象为失败
reject(e);
}
}
// 添加then方法
Promise.prototype.then = function(onResolved,onRejected){
//如果Promise状态为fulfilled回调这个函数
if(this.PromiseState === 'fulfilled'){
//将结果值传入
onResolved(this.PromiseResult);
}
//如果Promise状态为rejected回调这个函数
if(this.PromiseState === 'rejected'){
//将结果值传入
onRejected(this.PromiseResult);
}
//如果Promise状态为pending,保存回调函数
if(this.PromiseState === 'pending'){
this.callbacks.push({
onResolved: onResolved,
onRejected: onRejected
})
}
}
9.同步任务 then()的返回结果:
就是在then()里有实现有结果返回:
const result = p.then(value => {
console.log(value);
},reason => {
console.warn(reason);
})
console.log(result);
解决:
// 自定义函数Promise
function Promise(executor){
//添加状态属性与结果值属性
this.PromiseState = 'pending';
this.PromiseResult = null;
// 定义callback属性,保存pending状态的回调函数
this.callbacks = [];
//保存实例对象的this值
const that = this;
//自定义resolve函数,名字不一定用resolve
function resolve(data){
//判断状态是否修改过
if(that.PromiseState !== 'pending') return;
//改变状态属性
that.PromiseState = 'fulfilled'; // 或者 resolve
//改变结果值属性
that.PromiseResult =data;
//异步任务成功后执行回调函数
that.callbacks.forEach(item=>{
item.onResolved(data);
})
}
//自定义reject函数
function reject(data){
//判断状态是否修改过,改过就直接返回
if(that.PromiseState !== 'pending') return;
//改变状态属性
that.PromiseState = 'rejected';
//改变结果值属性
that.PromiseResult =data;
//异步任务失败后执行回调函数
that.callbacks.forEach(item=>{
item.onRejected(data);
})
}
try{
//同步调用【执行器函数】
executor(resolve,reject);
}catch(e){
//更改Promise对象为失败
reject(e);
}
}
// 添加then方法
Promise.prototype.then = function (onResolved, onRejected) {
return new Promise((resolve, reject) => {
//如果Promise状态为fulfilled回调这个函数
if (this.PromiseState === 'fulfilled') {
try {
//获取回调函数执行结果
let result = onResolved(this.PromiseResult);
//判断
if (result instanceof Promise) {
//如果是Promise对象
result.then(v => {
resolve(v);
}, r => {
reject(r);
})
} else {
//结果对象状态为【成功】
resolve(result);
}
} catch (e) {
reject(e);
}
}
//如果Promise状态为rejected回调这个函数
if (this.PromiseState === 'rejected') {
//将结果值传入
onRejected(this.PromiseResult);
}
//如果Promise状态为pending,保存回调函数
if (this.PromiseState === 'pending') {
this.callbacks.push({
onResolved: onResolved,
onRejected: onRejected
})
}
})
}
注:instanceof 运算符用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上。
10.异步任务 then()的返回结果:
(´ཀ`」 ∠)
用第9步执行异步任务return返回的会是pending状态。
解决:
// 自定义函数Promise
function Promise(executor){
//添加状态属性与结果值属性
this.PromiseState = 'pending';
this.PromiseResult = null;
// 定义callback属性,保存pending状态的回调函数
this.callbacks = [];
//保存实例对象的this值
const that = this;
//自定义resolve函数,名字不一定用resolve
function resolve(data){
//判断状态是否修改过
if(that.PromiseState !== 'pending') return;
//改变状态属性
that.PromiseState = 'fulfilled'; // 或者 resolve
//改变结果值属性
that.PromiseResult =data;
//异步任务成功后执行回调函数
that.callbacks.forEach(item=>{
item.onResolved(data);
})
}
//自定义reject函数
function reject(data){
//判断状态是否修改过,改过就直接返回
if(that.PromiseState !== 'pending') return;
//改变状态属性
that.PromiseState = 'rejected';
//改变结果值属性
that.PromiseResult =data;
//异步任务失败后执行回调函数
that.callbacks.forEach(item=>{
item.onRejected(data);
})
}
try{
//同步调用【执行器函数】
executor(resolve,reject);
}catch(e){
//更改Promise对象为失败
reject(e);
}
}
// 添加then方法
Promise.prototype.then = function (onResolved, onRejected) {
const that = this;
return new Promise((resolve, reject) => {
//如果Promise状态为fulfilled回调这个函数
if (this.PromiseState === 'fulfilled') {
try {
//将结果值传入
let result = onResolved(this.PromiseResult);
//判断
if (result instanceof Promise) {
//如果是Promise对象
result.then(v => {
resolve(v);
}, r => {
reject(r);
})
} else {
//结果对象状态为【成功】
resolve(result);
}
} catch (e) {
reject(e);
}
}
//如果Promise状态为rejected回调这个函数
if (this.PromiseState === 'rejected') {
//将结果值传入
onRejected(this.PromiseResult);
}
//如果Promise状态为pending,保存回调函数
if (this.PromiseState === 'pending') {
this.callbacks.push({
onResolved: function () {
try {
//执行成功回调函数
let result = onResolved(that.PromiseResult);
//判断
if (result instanceof Promise) {
result.then(v => {
resolve(v);
}, r => {
reject(r);
})
} else {
resolve(result);
}
} catch (e) {
reject(e);
}
},
onRejected: function () {
try {
//执行成功回调函数
let result = onRejected(that.PromiseResult);
//判断
if (result instanceof Promise) {
result.then(v => {
resolve(v);
}, r => {
reject(r);
})
} else {
resolve(result);
}
} catch(e){
reject(e);
}
}
})
}
})
}
11. 完善then()方法与优化:
// 自定义函数Promise
function Promise(executor){
//添加状态属性与结果值属性
this.PromiseState = 'pending';
this.PromiseResult = null;
// 定义callback属性,保存pending状态的回调函数
this.callbacks = [];
//保存实例对象的this值
const that = this;
//自定义resolve函数,名字不一定用resolve
function resolve(data){
//判断状态是否修改过
if(that.PromiseState !== 'pending') return;
//改变状态属性
that.PromiseState = 'fulfilled'; // 或者 resolve
//改变结果值属性
that.PromiseResult =data;
//异步任务成功后执行回调函数
that.callbacks.forEach(item=>{
item.onResolved(data);
})
}
//自定义reject函数
function reject(data){
//判断状态是否修改过,改过就直接返回
if(that.PromiseState !== 'pending') return;
//改变状态属性
that.PromiseState = 'rejected';
//改变结果值属性
that.PromiseResult =data;
//异步任务失败后执行回调函数
that.callbacks.forEach(item=>{
item.onRejected(data);
})
}
try{
//同步调用【执行器函数】
executor(resolve,reject);
}catch(e){
//更改Promise对象为失败
reject(e);
}
}
// 添加then方法
Promise.prototype.then = function (onResolved, onRejected) {
const that = this;
return new Promise((resolve, reject) => {
//封装重复的部分
function callback(type){
try {
//将结果值传入
let result = type(that.PromiseResult);
//判断
if (result instanceof Promise) {
//如果是Promise对象
result.then(v => {
resolve(v);
}, r => {
reject(r);
})
} else {
//结果对象状态为【成功】
resolve(result);
}
} catch (e) {
reject(e);
}
}
//如果Promise状态为fulfilled回调这个函数
if (this.PromiseState === 'fulfilled') {
callback(onResolved);
}
//如果Promise状态为rejected回调这个函数
if (this.PromiseState === 'rejected') {
callback(onRejected);
}
//如果Promise状态为pending,保存回调函数
if (this.PromiseState === 'pending') {
this.callbacks.push({
onResolved: function () {
callback(onResolved);
},
onRejected: function () {
callback(onRejected);
}
})
}
})
}
12. 实现catch方法与异常穿透:
// 自定义函数Promise
function Promise(executor){
//添加状态属性与结果值属性
this.PromiseState = 'pending';
this.PromiseResult = null;
// 定义callback属性,保存pending状态的回调函数
this.callbacks = [];
//保存实例对象的this值
const that = this;
//自定义resolve函数,名字不一定用resolve
function resolve(data){
//判断状态是否修改过
if(that.PromiseState !== 'pending') return;
//改变状态属性
that.PromiseState = 'fulfilled'; // 或者 resolve
//改变结果值属性
that.PromiseResult =data;
//异步任务成功后执行回调函数
that.callbacks.forEach(item=>{
item.onResolved(data);
})
}
//自定义reject函数
function reject(data){
//判断状态是否修改过,改过就直接返回
if(that.PromiseState !== 'pending') return;
//改变状态属性
that.PromiseState = 'rejected';
//改变结果值属性
that.PromiseResult =data;
//异步任务失败后执行回调函数
that.callbacks.forEach(item=>{
item.onRejected(data);
})
}
try{
//同步调用【执行器函数】
executor(resolve,reject);
}catch(e){
//更改Promise对象为失败
reject(e);
}
}
// 添加then方法
Promise.prototype.then = function (onResolved, onRejected) {
const that = this;
//判断回调参数是否存在
if(typeof onRejected !== 'function'){
onRejected = reason =>{
throw reason;
}
}
if(typeof onResolved !== 'function'){
onResolved = value => value;
}
return new Promise((resolve, reject) => {
//封装重复的部分
function callback(type){
try {
//将结果值传入
let result = type(that.PromiseResult);
//判断
if (result instanceof Promise) {
//如果是Promise对象
result.then(v => {
resolve(v);
}, r => {
reject(r);
})
} else {
//结果对象状态为【成功】
resolve(result);
}
} catch (e) {
reject(e);
}
}
//如果Promise状态为fulfilled回调这个函数
if (this.PromiseState === 'fulfilled') {
callback(onResolved);
}
//如果Promise状态为rejected回调这个函数
if (this.PromiseState === 'rejected') {
callback(onRejected);
}
//如果Promise状态为pending,保存回调函数
if (this.PromiseState === 'pending') {
this.callbacks.push({
onResolved: function () {
callback(onResolved);
},
onRejected: function () {
callback(onRejected);
}
})
}
})
}
//添加catch 方法
Promise.prototype.catch = function(onRejected){
return this.then(undefined,onRejected);
}
注:typeof 操作符返回一个字符串,表示未经计算的操作数的类型。
13.封装Promise.resolve方法
// 自定义函数Promise
function Promise(executor){
//添加状态属性与结果值属性
this.PromiseState = 'pending';
this.PromiseResult = null;
// 定义callback属性,保存pending状态的回调函数
this.callbacks = [];
//保存实例对象的this值
const that = this;
//自定义resolve函数,名字不一定用resolve
function resolve(data){
//判断状态是否修改过
if(that.PromiseState !== 'pending') return;
//改变状态属性
that.PromiseState = 'fulfilled'; // 或者 resolve
//改变结果值属性
that.PromiseResult =data;
//异步任务成功后执行回调函数
that.callbacks.forEach(item=>{
item.onResolved(data);
})
}
//自定义reject函数
function reject(data){
//判断状态是否修改过,改过就直接返回
if(that.PromiseState !== 'pending') return;
//改变状态属性
that.PromiseState = 'rejected';
//改变结果值属性
that.PromiseResult =data;
//异步任务失败后执行回调函数
that.callbacks.forEach(item=>{
item.onRejected(data);
})
}
try{
//同步调用【执行器函数】
executor(resolve,reject);
}catch(e){
//更改Promise对象为失败
reject(e);
}
}
// 添加then方法
Promise.prototype.then = function (onResolved, onRejected) {
const that = this;
//判断回调参数是否存在
if(typeof onRejected !== 'function'){
onRejected = reason =>{
throw reason;
}
}
if(typeof onResolved !== 'function'){
onResolved = value => value;
}
return new Promise((resolve, reject) => {
//封装重复的部分
function callback(type){
try {
//将结果值传入
let result = type(that.PromiseResult);
//判断
if (result instanceof Promise) {
//如果是Promise对象
result.then(v => {
resolve(v);
}, r => {
reject(r);
})
} else {
//结果对象状态为【成功】
resolve(result);
}
} catch (e) {
reject(e);
}
}
//如果Promise状态为fulfilled回调这个函数
if (this.PromiseState === 'fulfilled') {
callback(onResolved);
}
//如果Promise状态为rejected回调这个函数
if (this.PromiseState === 'rejected') {
callback(onRejected);
}
//如果Promise状态为pending,保存回调函数
if (this.PromiseState === 'pending') {
this.callbacks.push({
onResolved: function () {
callback(onResolved);
},
onRejected: function () {
callback(onRejected);
}
})
}
})
}
//添加catch 方法
Promise.prototype.catch = function(onRejected){
return this.then(undefined,onRejected);
}
//添加resolve方法
Promise.resolve = function(value){
//返回promise对象
return new Promise((resolve,reject) =>{
if(value instanceof Promise){
value.then(v=>{
resolve(v);
},r=>{
reject(r);
})
}else{
resolve(value);
}
})
}
注:instanceof 运算符用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上。
实践一下:
let p = Promise.resolve(new Promise((resolve,reject)=>{
reject('_(´ཀ`」 ∠)_');
}));
console.log(p);
14. 封装Promise.reject方法:
无论传入啥只返回一个失败的promise对象。
// 自定义函数Promise
function Promise(executor){
//添加状态属性与结果值属性
this.PromiseState = 'pending';
this.PromiseResult = null;
// 定义callback属性,保存pending状态的回调函数
this.callbacks = [];
//保存实例对象的this值
const that = this;
//自定义resolve函数,名字不一定用resolve
function resolve(data){
//判断状态是否修改过
if(that.PromiseState !== 'pending') return;
//改变状态属性
that.PromiseState = 'fulfilled'; // 或者 resolve
//改变结果值属性
that.PromiseResult =data;
//异步任务成功后执行回调函数
that.callbacks.forEach(item=>{
item.onResolved(data);
})
}
//自定义reject函数
function reject(data){
//判断状态是否修改过,改过就直接返回
if(that.PromiseState !== 'pending') return;
//改变状态属性
that.PromiseState = 'rejected';
//改变结果值属性
that.PromiseResult =data;
//异步任务失败后执行回调函数
that.callbacks.forEach(item=>{
item.onRejected(data);
})
}
try{
//同步调用【执行器函数】
executor(resolve,reject);
}catch(e){
//更改Promise对象为失败
reject(e);
}
}
// 添加then方法
Promise.prototype.then = function (onResolved, onRejected) {
const that = this;
//判断回调参数是否存在
if(typeof onRejected !== 'function'){
onRejected = reason =>{
throw reason;
}
}
if(typeof onResolved !== 'function'){
onResolved = value => value;
}
return new Promise((resolve, reject) => {
//封装重复的部分
function callback(type){
try {
//将结果值传入
let result = type(that.PromiseResult);
//判断
if (result instanceof Promise) {
//如果是Promise对象
result.then(v => {
resolve(v);
}, r => {
reject(r);
})
} else {
//结果对象状态为【成功】
resolve(result);
}
} catch (e) {
reject(e);
}
}
//如果Promise状态为fulfilled回调这个函数
if (this.PromiseState === 'fulfilled') {
callback(onResolved);
}
//如果Promise状态为rejected回调这个函数
if (this.PromiseState === 'rejected') {
callback(onRejected);
}
//如果Promise状态为pending,保存回调函数
if (this.PromiseState === 'pending') {
this.callbacks.push({
onResolved: function () {
callback(onResolved);
},
onRejected: function () {
callback(onRejected);
}
})
}
})
}
//添加catch 方法
Promise.prototype.catch = function(onRejected){
return this.then(undefined,onRejected);
}
//添加resolve方法
Promise.resolve = function(value){
//返回promise对象
return new Promise((resolve,reject) =>{
if(value instanceof Promise){
value.then(v=>{
resolve(v);
},r=>{
reject(r);
})
}else{
resolve(value);
}
})
}
//添加reject方法
Promise.reject = function(reason){
return new Promise((resolve,reject)=>{
reject(reason);
});
}
15. 封装Promise.all方法:
返回一个新的promise,只有所有的promise都成功才成功,只要有一个失败了就直接失败。失败了返回那个失败值。
// 自定义函数Promise
function Promise(executor){
//添加状态属性与结果值属性
this.PromiseState = 'pending';
this.PromiseResult = null;
// 定义callback属性,保存pending状态的回调函数
this.callbacks = [];
//保存实例对象的this值
const that = this;
//自定义resolve函数,名字不一定用resolve
function resolve(data){
//判断状态是否修改过
if(that.PromiseState !== 'pending') return;
//改变状态属性
that.PromiseState = 'fulfilled'; // 或者 resolve
//改变结果值属性
that.PromiseResult =data;
//异步任务成功后执行回调函数
that.callbacks.forEach(item=>{
item.onResolved(data);
})
}
//自定义reject函数
function reject(data){
//判断状态是否修改过,改过就直接返回
if(that.PromiseState !== 'pending') return;
//改变状态属性
that.PromiseState = 'rejected';
//改变结果值属性
that.PromiseResult =data;
//异步任务失败后执行回调函数
that.callbacks.forEach(item=>{
item.onRejected(data);
})
}
try{
//同步调用【执行器函数】
executor(resolve,reject);
}catch(e){
//更改Promise对象为失败
reject(e);
}
}
// 添加then方法
Promise.prototype.then = function (onResolved, onRejected) {
const that = this;
//判断回调参数是否存在
if(typeof onRejected !== 'function'){
onRejected = reason =>{
throw reason;
}
}
if(typeof onResolved !== 'function'){
onResolved = value => value;
}
return new Promise((resolve, reject) => {
//封装重复的部分
function callback(type){
try {
//将结果值传入
let result = type(that.PromiseResult);
//判断
if (result instanceof Promise) {
//如果是Promise对象
result.then(v => {
resolve(v);
}, r => {
reject(r);
})
} else {
//结果对象状态为【成功】
resolve(result);
}
} catch (e) {
reject(e);
}
}
//如果Promise状态为fulfilled回调这个函数
if (this.PromiseState === 'fulfilled') {
callback(onResolved);
}
//如果Promise状态为rejected回调这个函数
if (this.PromiseState === 'rejected') {
callback(onRejected);
}
//如果Promise状态为pending,保存回调函数
if (this.PromiseState === 'pending') {
this.callbacks.push({
onResolved: function () {
callback(onResolved);
},
onRejected: function () {
callback(onRejected);
}
})
}
})
}
//添加catch 方法
Promise.prototype.catch = function(onRejected){
return this.then(undefined,onRejected);
}
//添加resolve方法
Promise.resolve = function(value){
//返回promise对象
return new Promise((resolve,reject) =>{
if(value instanceof Promise){
value.then(v=>{
resolve(v);
},r=>{
reject(r);
})
}else{
resolve(value);
}
})
}
//添加reject方法
Promise.reject = function(reason){
return new Promise((resolve,reject)=>{
reject(reason);
});
}
//添加all方法
Promise.all = function(promises){
return new Promise((resolve,reject) => {
//添加变量
let count = 0;
// 存放成功结果数组
let arr =[];
//遍历全部
for (let i = 0; i < promises.length; i++) {
promises[i].then(v => {
//能进到证明其为成功
count++;
//保存成功结果
arr[i]=v;
//如果全部成功
if (count === promises.length) {
//状态为成功
resolve(arr);
}
}, r => {
//能进到证明其为失败
reject(r);
});
}
});
}
试一下:
let p1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('111')
}, 1000)
})
const p2 = Promise.resolve('222')
const p3 = Promise.resolve('333')
let result = Promise.all([p1, p2, p3])
console.log(result);
结果:
16. 封装Promise.race方法:
返回一个新的promise,第一个完成的promise的结果状态改变的就是最终的结果状态。
上面重复的代码就不写上了:
//添加race方法
Promise.race = function(promises){
return new Promise((resolve,reject) => {
//遍历全部
for (let i = 0; i < promises.length; i++) {
promises[i].then(v => {
//能进到证明其为成功
//状态为成功
resolve(v);
}, r => {
//能进到证明其为失败
reject(r);
})
}
});
}
试一下:
let p1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('111')
}, 1000)
})
const p2 = Promise.resolve('222')
const p3 = Promise.resolve('333')
let result = Promise.race([p1, p2, p3])
console.log(result);
运行结果:注意跟传入的数组元素顺序也有关,若传入[p1,p3,p2],从左到右执行,结果为p3
运行结果:
17.回调函数异步执行:
原生promise的执行顺序:
let p1 = new Promise((resolve, reject) => {
resolve('ok')
console.log(111);
})
p1.then(value=>{
// console.log(value);
console.log(222);
})
console.log(333);
输出结果:
111
333
222
上面回调函数还是同步执行的,要让 then()回调函数异步执行。
添加定时器模仿异步操作:
// 自定义函数Promise
function Promise(executor){
//添加状态属性与结果值属性
this.PromiseState = 'pending';
this.PromiseResult = null;
// 定义callback属性,保存pending状态的回调函数
this.callbacks = [];
//保存实例对象的this值
const that = this;
//自定义resolve函数,名字不一定用resolve
function resolve(data) {
//判断状态是否修改过
if (that.PromiseState !== 'pending') return;
//改变状态属性
that.PromiseState = 'fulfilled'; // 或者 resolve
//改变结果值属性
that.PromiseResult = data;
//异步任务成功后执行回调函数
setTimeout(() => {
that.callbacks.forEach(item => {
item.onResolved(data);
})
});
}
//自定义reject函数
function reject(data) {
//判断状态是否修改过,改过就直接返回
if (that.PromiseState !== 'pending') return;
//改变状态属性
that.PromiseState = 'rejected';
//改变结果值属性
that.PromiseResult = data;
//异步任务失败后执行回调函数
setTimeout(() => {
that.callbacks.forEach(item => {
item.onRejected(data);
})
});
}
try{
//同步调用【执行器函数】
executor(resolve,reject);
}catch(e){
//更改Promise对象为失败
reject(e);
}
}
// 添加then方法
Promise.prototype.then = function (onResolved, onRejected) {
const that = this;
//判断回调参数是否存在
if(typeof onRejected !== 'function'){
onRejected = reason =>{
throw reason;
}
}
if(typeof onResolved !== 'function'){
onResolved = value => value;
}
return new Promise((resolve, reject) => {
//封装重复的部分
function callback(type){
try {
//将结果值传入
let result = type(that.PromiseResult);
//判断
if (result instanceof Promise) {
//如果是Promise对象
result.then(v => {
resolve(v);
}, r => {
reject(r);
})
} else {
//结果对象状态为【成功】
resolve(result);
}
} catch (e) {
reject(e);
}
}
//如果Promise状态为fulfilled回调这个函数
if (this.PromiseState === 'fulfilled') {
setTimeout(()=>{
callback(onResolved);
});
}
//如果Promise状态为rejected回调这个函数
if (this.PromiseState === 'rejected') {
setTimeout(()=>{
callback(onRejected);
});
}
//如果Promise状态为pending,保存回调函数
if (this.PromiseState === 'pending') {
this.callbacks.push({
onResolved: function () {
callback(onResolved);
},
onRejected: function () {
callback(onRejected);
}
})
}
})
}
//添加catch 方法
Promise.prototype.catch = function(onRejected){
return this.then(undefined,onRejected);
}
//添加resolve方法
Promise.resolve = function(value){
//返回promise对象
return new Promise((resolve,reject) =>{
if(value instanceof Promise){
value.then(v=>{
resolve(v);
},r=>{
reject(r);
})
}else{
resolve(value);
}
})
}
//添加reject方法
Promise.reject = function(reason){
return new Promise((resolve,reject)=>{
reject(reason);
});
}
//添加all方法
Promise.all = function(promises){
return new Promise((resolve,reject) => {
//添加变量
let count = 0;
// 存放成功结果数组
let arr =[];
//遍历全部
for (let i = 0; i < promises.length; i++) {
promises[i].then(v => {
//能进到证明其为成功
count++;
//保存成功结果
arr[i]=v;
//如果全部成功
if (count === promises.length) {
//状态为成功
resolve(arr);
}
}, r => {
//能进到证明其为失败
reject(r);
});
}
});
}
//添加race方法
Promise.race = function(promises){
return new Promise((resolve,reject) => {
//遍历全部
for (let i = 0; i < promises.length; i++) {
promises[i].then(v => {
//能进到证明其为成功
//状态为成功
resolve(v);
}, r => {
//能进到证明其为失败
reject(r);
})
}
});
}
18.class版本封装:
最终封装:
class Promise{
//构造方法
constructor(executor) {
//添加状态属性与结果值属性
this.PromiseState = 'pending';
this.PromiseResult = null;
// 定义callback属性,保存pending状态的回调函数
this.callbacks = [];
//保存实例对象的this值
const that = this;
//自定义resolve函数,名字不一定用resolve
function resolve(data) {
//判断状态是否修改过
if (that.PromiseState !== 'pending') return;
//改变状态属性
that.PromiseState = 'fulfilled'; // 或者 resolve
//改变结果值属性
that.PromiseResult = data;
//异步任务成功后执行回调函数
setTimeout(() => {
that.callbacks.forEach(item => {
item.onResolved(data);
})
});
}
//自定义reject函数
function reject(data) {
//判断状态是否修改过,改过就直接返回
if (that.PromiseState !== 'pending') return;
//改变状态属性
that.PromiseState = 'rejected';
//改变结果值属性
that.PromiseResult = data;
//异步任务失败后执行回调函数
setTimeout(() => {
that.callbacks.forEach(item => {
item.onRejected(data);
})
});
}
try{
//同步调用【执行器函数】
executor(resolve,reject);
}catch(e){
//更改Promise对象为失败
reject(e);
}
}
//then方法封装
then(onResolved,onRejected){
const that = this;
//判断回调参数是否存在
if(typeof onRejected !== 'function'){
onRejected = reason =>{
throw reason;
}
}
if(typeof onResolved !== 'function'){
onResolved = value => value;
}
return new Promise((resolve, reject) => {
//封装重复的部分
function callback(type){
try {
//将结果值传入
let result = type(that.PromiseResult);
//判断
if (result instanceof Promise) {
//如果是Promise对象
result.then(v => {
resolve(v);
}, r => {
reject(r);
})
} else {
//结果对象状态为【成功】
resolve(result);
}
} catch (e) {
reject(e);
}
}
//如果Promise状态为fulfilled回调这个函数
if (this.PromiseState === 'fulfilled') {
setTimeout(()=>{
callback(onResolved);
});
}
//如果Promise状态为rejected回调这个函数
if (this.PromiseState === 'rejected') {
setTimeout(()=>{
callback(onRejected);
});
}
//如果Promise状态为pending,保存回调函数
if (this.PromiseState === 'pending') {
this.callbacks.push({
onResolved: function () {
callback(onResolved);
},
onRejected: function () {
callback(onRejected);
}
})
}
})
}
//catch 方法
catch(onRejected){
return this.then(undefined,onRejected);
}
//resolve方法
static resolve(value){
//返回promise对象
return new Promise((resolve,reject) =>{
if(value instanceof Promise){
value.then(v=>{
resolve(v);
},r=>{
reject(r);
})
}else{
resolve(value);
}
})
}
//reject方法
static reject(reason){
return new Promise((resolve,reject)=>{
reject(reason);
});
}
//all方法
static all(promises) {
return new Promise((resolve, reject) => {
//添加变量
let count = 0;
// 存放成功结果数组
let arr = [];
//遍历全部
for (let i = 0; i < promises.length; i++) {
promises[i].then(v => {
//能进到证明其为成功
count++;
//保存成功结果
arr[i] = v;
//如果全部成功
if (count === promises.length) {
//状态为成功
resolve(arr);
}
}, r => {
//能进到证明其为失败
reject(r);
});
}
});
}
//race方法
static race(promises) {
return new Promise((resolve, reject) => {
//遍历全部
for (let i = 0; i < promises.length; i++) {
promises[i].then(v => {
//能进到证明其为成功
//状态为成功
resolve(v);
}, r => {
//能进到证明其为失败
reject(r);
})
}
});
}
}
十一、async函数
1.函数的返回值为promise对象。
2.promise对象的结果由async函数执行的返回值决定。
3.其实跟 then()方法返回结果是一模一样的。
1.返回一个非Promise对象,返回值是resolve。
async function main(){
return '123';
}
let res = main();
console.log(res);
2.如果返回是一个Promise对象,由返回结果决定:
async function main(){
return new Promise((resolve,reject)=>{
reject('NO');
});
}
let res = main();
console.log(res);
3.抛出异常也是失败:
async function main() {
return new Promise((resolve,reject)=>{
throw 'error'
})
}
let result = main()
console.log(result);
十二、await表达式
1.await右侧的表达式一般为promise对象,但也可以是其它的值。
2.如果表达式是promise对象,await返回的是promise成功的值。
3.如果表达式是其它值,直接将此值作为await的返回值。
注意:
1.await 必须写在async函数中,但async 函数中可以没有await 。
2.如果await的promise失败了,就会抛出异常,需要通过try…catch捕获处理。
1.右侧为promise对象:
async function works(){
let p = new Promise((resolve,reject)=>{
resolve('oh yes')
})
let res = await p;
console.log(res);
}
works();
结果:
oh yes
2.右侧为其它值:
async function works(){
let p = new Promise((resolve,reject)=>{
resolve('oh yes')
})
// let res = await p;
let res = await 100;
console.log(res);
}
works();
结果:
100
3.如果promise是失败状态:
async function works(){
let p = new Promise((resolve,reject)=>{
// resolve('oh yes')
reject('err');
})
try{
let res = await p;
}catch(e){
console.log(e);
}
}
works();
回顾一下async函数的返回值问题
async function works() {
let p = new Promise((resolve, reject) => {
// resolve('oh yes')
reject('err');
})
try {
let res = await p;
} catch (e) {
console.log(e);
}
}
let result = works();
console.log(result);
运行结果:(async函数没有返回值,所以promise结果是undefined)
十三、async与await结合发送AJAX请求
效果: 点击按钮获取一句名言。
<button id="btn">点击获取段子</button>
<script>
function sendAJAX(url) {
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.responseType = 'json';
xhr.open('GET', url)
xhr.send()
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
if (xhr.status >= 200 && xhr.status < 300) {
resolve(xhr.response)
} else {
reject(xhr.status)
}
}
}
})
}
let btn = document.querySelector('#btn')
btn.addEventListener('click', async function () {
// 获取段子信息
try {
let duanzi = await sendAJAX("http://poetry.apiopen.top/sentences")
console.log(duanzi);
} catch (e) {
console.log(e);
}
})
</script>