(14)es6——promise

promise构造函数

基本使用

Promise构造函数接收一个函数,这个函数是同步执行的,
当这个Promise构造函数被调用时,传入的函数中的代码
是一个同步代码,而不是js的异步任务。
这个函数接收两个参数(他们两都是函数)
const p = new Promise((resolve, reject) => {
  console.log("执行1");
  resolve("成功");
});
console.log("执行2");
console.log(p);

Promise的工作流程

在这里插入图片描述
在这里插入图片描述

我们发现"执行1","执行2"按照正常的书写顺序输出了。说明Promise构造函数的参数函数中
代码是同步代码。

Promise的状态

pending(进行中)
fulfilled(已成功)
rejected(已失败)

Promise.resolve()

resolve()传入一个promise对象,那么返回值是一个promise对象,状态和值由
“传入的promise对象”决定。
传入一个非promise对象,返回值是一个promise对象,状态永远为已完成,
值为传入的值。
const p1 = Promise.resolve(521);
const p2 = Promise.resolve(new Promise((resolve,reject)=>{
  		resolve('成功');
}));
// 传入一个错误,p3的状态还是成功
const p3 = Promise.resolve(new Error('错误'));
const p4 = Promise.resolve(new Promise((resolve,reject)=>{
	reject('失败');
}))
console.log(p1);
console.log(p2);
console.log(p3);
console.log(p4);

在这里插入图片描述

Promise.reject()

reject()传入一个promise对象,那么返回值是一个promise对象,
状态永远为失败,值是传入的promise对象
传入一个非promise对象,返回值是一个失败的promise对象,
状态永远为失败,值为传入的值
const p1 = Promise.reject(521);
const p2 = Promise.reject(new Promise((resolve,reject)=>{
   resolve('成功');
 }))
const p3 = Promise.reject(new Promise((resolve,reject)=> {
	reject('失败');
}))
console.log(p1);
console.log(p2); 
console.log(p3);

在这里插入图片描述

Promise.all()

接收多个promise对象组成的数组。
只有当所有的promise对象的状态都为已完成,返回的promise对象的状态才为已完成。
当状态为已完成时,值为各个promise对象的值组成的数组。
当状态为已失败时,值为第一个失败的promise对象的值。
const p = Promise.all([
  new Promise((resolve, reject) => {
    resolve("成功1");
  }),
  new Promise((resolve, reject) => {
    resolve("成功2");
  }),
  new Promise((resolve, reject) => {
    reject("失败1");
  }),
  new Promise((resolve,reject)=>{
    reject("失败2")
  })
]);
console.log(p);

在这里插入图片描述

Promise.race()

race(竞速的意思)顾名思义:接收promise对象组成的数组,值和状态由第一个返回值和状态的promise对象决定。
const p1 = new Promise((resolve, reject) => {
setTimeout(() => {
  console.log("成功1");
  resolve("成功1");
  }, 2000);
});

const p2 = new Promise((resolve, reject) => {
  setTimeout(() => {
  console.log("失败");
  reject("err");
  }, 1000);
});
let p = Promise.race([p1, p2]);
setTimeout(() => {
  console.log(p);
}, 1000);

在这里插入图片描述

Promise.prototype.then/catch()/finally()

const p = new Promise((resolve,reject) => {
  // resolve('成功')
  reject('失败')
}).then((value)=>{
  console.log(value); // '成功'
}).catch((err)=>{
  console.log(err); // '失败'
}).finally(()=>{
  // 不管promise最后的状态,在执行完then或catch指定的回调函数以后,都会执行finally方法指定的回调函数
  console.log("不管promise的状态,我永远会输出");
})

es11新增Promise.allSettled()

const p1 = new Promise(function(resolve, reject) {
	setTimeout(function() {
		resolve('p1成功');
	}, 1000)
})

const p2 = new Promise(function(resolve, reject) {
	setTimeout(function() {
		reject('p2失败');
	}, 1000)
})

// 返回一个promise对象,状态属性永远是fulfilled完成,值属性的值是一个数组,数组每一项是每个promise对象的状态和值对象
const result1 = Promise.allSettled([p1, p2]);

// 相似方法all,也是返回一个promise对象,状态由传入的promise对象决定,都为完成时,返回的promise对象的状态才为完成,值为一个数组,数组每一项是每个promise对象的值。有失败的话,状态为失败,值为第一个失败的promise的值。
const result2 = Promise.all([p1,p2]);
console.log(result1);
console.log(result2);

在这里插入图片描述

在这里插入图片描述

Promise的注意事项

Promise.then()方法的返回值由谁决定

then方法可以只写第一个参数,也就是状态为已完成时调用的函数
then()方法返回一个promise对象,这样就可以进行链式调用了,解决回调地狱
const p = new Promise(function(resolve,reject){
setTimeout(function(){
	let data = '用户数据';
	resolve(data);
},1000)
})
const result = p.then(function(value){
// 1、默认return 返回一个 undefined,状态为已完成,值为undefined
console.log(value);
// 2、return的值不是一个promise对象时,状态为已完成,值为return的值
// return 123
// 3、throw抛出一个结果,状态为拒绝,值为抛出的值
// throw '123'
// 4、抛出一个error错误对象,状态为拒绝,值为抛出的error对象
// throw new Error('123');
// 5、return一个promise对象,状态为下一级promise对象的状态,值也是下一级promise的值
return new Promise(function(resolve,reject){
	// promise封装异步操作,也可以执行同步代码
	// resolve('123');
	reject('123');
})
})
console.log(result);

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

promise怎么串联调用多个同步异步任务

let p1 = new Promise((resolve, reject) => {
    resolve("p1成功");
});

let p2 = p1.then((value) => {
    return new Promise((resolve, reject) => {
            console.log(value); // p1成功
            resolve("p2成功");
        })
        .then((value) => {
            console.log(value); // p2成功
            // return {PromiseState:fulfilled,PromiseResult:undefined}
        })
        .then((value) => {
            console.log(value); //undefined,因为上一个then默认return了一个{PromiseState:fulfilled,PromiseResult:undefined}
        });
});

在这里插入图片描述

promise的异常穿透

在then链式调用的时候在最后指定错误的回调,不管是链式调用的哪个环节失败了,
都只需要在最后指定失败的回调即可
let p1 = new Promise((resolve, reject) => {
        resolve("成功");
    })
    .then(value => {
        return new Promise((resolve, reject) => {
            reject("err1");
        });
    })
    // 因为上一个then已失败,故不会继续执行后面的then。
    .then(value => {
        return new Promise((resolve, reject) => {
            reject("err2");
        });
    })
    .catch(err => {
        console.log(err); // err1
    });

在这里插入图片描述

一个promise怎么指定多个成功或者失败的回调函数

const p = new Promise((resolve, reject) => {
    resolve("ok");
});
p.then((value) => {
    console.log(value);
});
p.then((value) => {
    console.log(value + "2");
});

在这里插入图片描述

先改变状态还是先执行回调

当执行器中是同步任务的时候,先改变状态后执行回调
const p = new Promise((resolve, reject) => {
  resolve("OK");
});
p.then(
  value => {
    console.log(value);
  },
  reason => {
    console.log(reason);
  }
);
console.log(p);

在这里插入图片描述

当执行器中是异步任务的时候,先执行回调后改变状态。
当p.then()需要异步操作更长的时间的,先改变状态后执行回调。
const p = new Promise((resolve, reject) => {
// 当执行器中是异步任务的时候,先执行回调后改变状态。
  setTimeout(()=>{
    resolve("OK");
  },1000)
});
p.then(
  value => {
    console.log(value);
  },
  reason => {
    console.log(reason);
  }
);
setInterval(()=>{
  console.log(p);
},10)

在这里插入图片描述

可以改变promise状态的方法

1、resolve
2、reject
3、throw
const p = new Promise((resolve,reject)=>{
  // 1.resolve 成功
  // resolve('OK');
  // 2.reject 失败
  // reject('err');
  // 3.throw 失败
  throw 123;
})
console.log(p);

在这里插入图片描述

如何中断链式调用链

打断链式调用的唯一方式,返回一个pedding状态的promise对象,也就是未有修改promise
状态代码的Promise对象
let p = new Promise((resolve, reject) => {
  resolve('成功')
}).then(value=>{
  console.log(value); // 成功
}).then(value=>{
  console.log(value); // undefined,前一个then默认返回
  // 在这。。。
  return new Promise((resolve,reject)=>{}) // 在这打断
}).then(value=>{
  console.log(value); // 前面被打断了,不会被调用
  console.log('调用到我这来了吗?'); // 前面被打断了,不会被调用
})

在这里插入图片描述

promise会开启一个微任务

具体解析可以看js专栏的中宏任务与微任务,并为大家讲解一道面试题帮助大家理解。

Promise的使用场景

promise链式调用解决回调地狱

const fs = require('fs');
// 回调地狱,读取文件,获取读取数据库中的数据有先后顺序时
// fs.readFile('./files/文件1.md',function(err1,data1){
// 	fs.readFile('./files/文件2.md',function(err2,data2){
// 		fs.readFile('./files/文件3.md',function(err3,data3){
// 			let result = data1 + data2 + data3;
// 			console.log(result);
// 		})
// 	})
// })

// 使用promise封装
const p = new Promise(function(resolve,reject){
	fs.readFile('./files/文件1.md',function(err,data){
		resolve(data);
	})
}).then(function(value){
	return new Promise(function(resolve,reject){
		fs.readFile('./files/文件2.md',function(err,data){
			resolve([value,data]);
		})
	})
}).then(function(value){
	return new Promise(function(resolve,reject){
		fs.readFile('./files/文件3.md',function(err,data){
			value.push(data);
			let result = value.join(';');
			console.log(result);
		})
	})
})

使用promise封装读取文件

const fs = require('fs');

// 不使用promise封装
// fs.readFile('./files/文件1.md',function(err,data){
// 	if(err) throw err;
// 	// buffer转字符
// 	console.log(data.toString());
// })

// 使用promise封装
const p = new Promise(function(resolve,reject){
	fs.readFile('./files/文件1.md',function(err,data){
		// reject和resolve方法都有终止代码向下执行的功能
		if(err) reject(err);
		resolve(data)
	})
})

p.then(function(value){
	console.log(value.toString());
},function(reason){
	console.log(reason);
})

使用promise封装ajax请求

 <!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8">
    <title></title>
</head>

<body>
    <script type="text/javascript">
        function a() {
            return new Promise(function(resolve, reject) {
                const xhr = new XMLHttpRequest();
                xhr.open("GET", "https://api.apiopen.top/getJoke");
                xhr.send();
                xhr.onreadystatechange = function() {
                    if (xhr.readyState === 4) {
                        if (xhr.status >= 200 && xhr.status < 300) {
                            resolve(xhr.response);
                            console.log(xhr.response);
                        } else {
                            reject(xhr.status);
                        }
                    }
                };
            });
        }
        a().then(
            function(value) {
                console.log(value);
            },
            function(reason) {
                console.error(reason);
            }
        );
    </script>
</body>

</html>

在这里插入图片描述

axios

前端与后端通信最常见的axios也是基于promise封装的。
有时间也是准备为大家更新博客怎么手写promise和axios。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

LiuJie_Boom

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值