一、介绍
1.概念:Promise是es6中新增的一个内置构造函数,它的参数是一个函数,这个函数又有两个参数resolve和reject,resolve和reject也都是函数
resolve(成功结果) 触发.then()小括号里函数体执行
reject(失败结果) 触发.catch()小括号里函数体执行
2.作用:主要是用来优化异步代码(异步解决方案)
3.优点:链式操作降低了编码难度,代码的可读性更高
二、基本语法
const p = new Promise((resolve, reject) => {
resolve(1)
//reject(2)
})
p.then(res => {
console.log('成功啦', res);
}).catch(err => {
console.log('出错啦', err);
}).finally(() => {
console.log('不管成功还是失败,这里都会执行~');
})
三、状态
1.pending 初始化状态 准备中
new出一个实例化Promise对象后就是准备状态
2.resolved/fulfilled 成功
当Promise内代码执行了resolve, 会导致所在的Promise对象 变成 resolved/fulfilled成功状态
3.rejected 失败
当Promise内代码执行了reject, 会导致所在的Promise对象 变成 rejected失败状态
四、值
1.resolve(值),这个值会自动传递给then
2.reject(值),这个值会自动传递给catch
五、实例方法
1.then()
(1)概念:then是实例状态发生改变时执行的回调函数
(2)参数:参数1 resolved状态的回调函数 ;参数2 rejected状态的回调函数
(3)返回值:新的实例化Promise
//p是一个Promise对象
p.then(函数1[,函数2])
当p的状态从pending变成了resolved,函数1会执行
当p的状态从pending变成了rejected,函数2会执行
一般第二个参数可以省略不写
注意:then()的返回值是一个新promise对象,这个新promise对象的状态和值如何确定?
var p1 = new Promise(()=>{});
var p2 = p1.then(function ok(){}, function err(){});
// p1 p2都是一个promise对象。console.log(p1 === p2); // false
情况1.如果p1的状态是pending,那么p2的状态也是pending 还在准备中就没有值
情况2.如果p1的状态是resolved ,then里面会执行ok这个函数,那么p2的返回值和状态由ok这个函数来决定
2.1如果ok返回值是一个promise对象,则p2的状态和值都以这个promise对象为准
2.2如果ok返回值不是promise对象,则p2的状态是resolved,值就是ok函数的return值
2.3如果ok这个函数内部发生了错误,则p2的状态是rejected,值就是这个错误对象
情况3.如果p1的状态是rejected,then会去执行err这个函数,则p2的状态由err的返回值决定
2.1如果err返回值是一个promise对象,则p2的状态和值都以这个promise对象为准
2.2如果err返回值不是promise对象,则p2的状态是resolved,值就是err函数的return值
2.3如果err这个函数内部发生了错误,则p2的状态是rejected,值就是这个错误对象
代码感受一下:
var p1 = new Promise(()=>{});
var p2 = p1.then(function f_ok(){}, function f_err(){}); // p2也是一个promise对象。
console.dir(p1); // pending
console.dir(p2); // pending
var p1 = new Promise((resolve,reject)=>{ resolve()});
var p2 = p1.then(function f_ok(){
var temp = new Promise((resolve,reject)=>{ resolve({a:1}) });
return temp;
}, function f_err(){});console.dir(p2); // resolved, {a:1}
var p1 = new Promise((resolve,reject)=>{ resolve()});
var p2 = p1.then(function f_ok(){
console.log(abc); // 这里故意犯错
}, function f_err(){});console.dir(p2);
2.catch()
一般来说,使用catch 方法代替then()第二个参数
返回值:也是一个新的promise对象
作用:捕获promise抛出的错误
3.finally()
不管 Promise 对象最后状态如何,finally()方法里面的代码都会执行
六、静态方法
1.all()
作用: 合并多个Promise对象, 等待所有成功后, 返回结果
参数: 是一个由多个Promise对象组成的数组
返回值: 返回的结果是个数组, 值是Promise对象按顺序排列的成功结果
p1,p2,p3全成功,p则成功,返回数组
p1,p2,p3只要有一个不成功,p就失败,返回的是第一个失败的promise的返回值
const p = Promise.race([p1, p2, p3]);
2.allSettled()
参数和作用和all()方法一样
返回值: 是一个数组 无论p1,p2,p3是否成功 都逐一对应返回p1,p2,p3的状态和值
3.race()
作用: 发起并行多个Promise对象, 等待只要任何一个有结果(成功|失败), 返回结果执行then
参数: 是一个由多个Promise对象组成的数组
返回值:第一个有结果的promise对象的结果
简单来说 谁先成功或失败就返回谁的值
4.resolve()
创建一个状态为resolved的promise对象
5.reject()
创建一个状态为rejected的promise对象
七、真实面试题:
让sleep 的功能与setTimeout一样:就是等2000毫秒之后再执行then中的回调函数
function sleep(time) {
// 请写出你的代码
return new Promise((resolve, reject) => {
setTimeout(resolve, time)
})
}
sleep(2000).then(() => {
console.log("后续操作")
})
console.log(2);
八、封装自己的ajax请求
function myAjax({ url, method = "GET" }) {
const xhr = new XMLHttpRequest()
xhr.open(method, url)
xhr.send()
const p = new Promise((resolve, reject) => {
xhr.addEventListener('load', () => {
if (xhr.status >= 200 && xhr.status < 400) {
resolve(JSON.parse(xhr.response))
} else {
reject(JSON.parse(xhr.response))
}
})
})
return p
}
//测试-----------------------------------------------------------------------
myAjax({
url: '',
// method: ''
}).then(res => {
console.log(res);
}).catch(err => {
console.log(err);
})