Promise学习记录
定义
异步编程的解决方案。
特点
- 对象状态不受外界影响
- 一旦状态改变就不会再变,任何时候获取的都是改变后的结果。
三种状态
- pending: 进行中
- fulfilled/resolved:已成功
- rejected: 已失败
状态改变
1、 pending转为fulfilled
2、pending转为rejected
有且仅有以上俩种状态转变,且不可逆转
基本用法
let p = new Promise((resolve, reject) => {});
console.log(p);
- Promise构造函数接收俩个参数(函数)
- resolve: 将Promise对象的状态从“未完成”变为“成功”(即从 pending 变为 resolved),在异步操作成功时调用,并将异步操作的结果,作为参数传递出去
- reject::将Promise对象的状态从“未完成”变为“失败”(即从 pending 变为 rejected),在异步操作失败时调用,并将异步操作报出的错误,作为参数传递出去。
- 在p实例中除prototype外还有俩个属性: promiseState、 PromiseResult.
Promise实例生成以后,可以用then方法分别指定resolved状态和rejected状态的回调函数。
let p = new Promise((resolve,reject)=>{
resolve('resolve函数将Promise状态从pending变成resolved')
})
p.then((res)=>{
console.log(res,'Promise对象的状态变为resolved时调用');
},(err)=>{
console.log(err, 'Promise对象的状态变为rejected时调用');
})
let p = new Promise((resolve,reject)=>{
reject('resolve函数将Promise状态从pending变成rejected')
})
p.then((res)=>{
console.log(res,'Promise对象的状态变为resolved时调用');
},(err)=>{
console.log(err, 'Promise对象的状态变为rejected时调用');
})
Promsie一旦被建就会立即执行
let p = new Promise((resolve,reject)=>{
console.log('Promise');
resolve()
})
p.then(res=>{
console.log('resolved');
})
console.log(123);
resolve函数除了正常的参数外,还可以是Promise实例
let p1 = new Promise((resolve,reject)=>{
resolve('123')
})
let p2 = new Promise((resolve,reject)=>{
resolve(p1)
})
p2.then(res=>{
console.log(res);
})
如果resolve的参数为Promsie实例时,前一个Promise的状态为pending,则后一个promise的回调函数需等前一个promise状态改变后执行;如果前一个状态为fulfilled或rejected,则后一个promise的回调函数回立即执行
const p1 = new Promise((resolve, reject) => {});
const p2 = new Promise((resolve, reject) => {
resolve(p1);
});
p2.then((res) => {
console.log(res);
}).catch((err) => {
console.log(err);
});
// p1的状态始终为pending,p2的回调函数不执行
const p1 = new Promise((resolve, reject) => {
resolve('p1状态改为fulfilled')
});
const p2 = new Promise((resolve, reject) => {
resolve(p1);
});
p2.then((res) => {
console.log(res); // p1状态改为fulfilled
}).catch((err) => {
console.log(err);
});
// p1的状态由pending转为fulfilled后,p2回调函数执行,并将p1作为参数传递
const p1 = new Promise((resolve, reject) => {
setTimeout(()=>{
reject(new Error('p1的状态改为rejected'))
},1000)
});
const p2 = new Promise((resolve, reject) => {
resolve(p1);
});
p2.then((res) => {
console.log(res);
}).catch((err) => {
console.log(err); // Error: p1的状态改为rejected
});
// p1的状态由pending转为rejected后,p2回调函数执行,并将p1作为参数传递
通过Promise实现ajax请求
let p = new Promise((resolve, reject) => {
let xhr = new XMLHttpRequest();
xhr.open("GET", "url");
xhr.send();
xhr.responseType ='json'
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
resolve(xhr.response)
} else {
reject(xhr.status);
}
}
};
});
p.then(
(res) => {
console.log(res, "res");
},
(err) => {
console.log(err, "err");
}
);
实例方法
- Promise.prototype.then()
- 用于为Promise添加状态改变时的回调函数
- 俩个参数(函数):状态为fulfilled时的回调, 状态为rejected的回调
- 返回的是一个新的Promise对象,因此可以使用链式调用
const p = new Promise((resolve, reject
resolve("data");
});
p.then((res) => {
console.log(res, "then1");
return res;
})
.then((res) => {
console.log(res, "then2");
})
.then((res) => {
console.log(res, "then3");
});
以上代码创建了Promise实例p,通过第一个then方法调用,输出data,第一个then方法又是一个新的Promise实例,并将上述状态返回,于是通过第二个then方法调用可输出data,而第二个then方法无任何返回值,所以第三个then方法调用时接收不到任何值,所以返回undefined
2. Promise.prototype.catch()
- 用于指定发生错误的回调函数
const p = new Promise((resolve, r
reject(new Error("err"));
});
p.then((res) => {}).catch((err) =
console.log(err); // Error: er
});
// 如果p的状态为fulfilled,则执行then方法,如果then方法中跑出异常也会执行catch
const p = new Promise((resolve, reject) => {
resolve('resolved')
});
p.then((res) => {
throw '抛出异常'
}).catch((err) => {
console.log(err); // Error: err
});
建议: then方法的第二个参数使用调用catch方法代替,因为catch方法还是一个Promise对象,除可以处理promise内部的错误外还可以继续调用后面的then方法
const p = new Promise((resolve, reject) => {
reject(new Error("出错了"));
});
p.catch((err) => {
console.log(err, "err");
}).then((res) => {
console.log(res, 'then函数在catch执行后也被执行了');
});
const p = new Promise((resolve, reject) => {
resolve(x + 2);
});
p.catch((err) => {
console.log(err, "err");
}).then((res) => {
console.log(res, "then函数在catch执行后也被
});
- 如果状态为fulfilled则可跳过catch方法
const p = new Promise((resolve, reject)
let x = 3
resolve(x + 2);
});
p.catch((err) => {
console.log(err, "err");
}).then((res) => {
console.log(res, "then函数执行了");
});
- catch自身的错误只能被下一个catch捕获
const p = new Promise((resolve, reject) =
resolve(x + 2);
});
p.catch((err) => {
console.log(err, "promise实例出错");
y + 1;
}).catch((err) => {
console.log(err, "上一个catch出错");
});
3. Promise.prototype.finally()
- 无论Promise最后的状态如何都会执行的操作
Promise常用方法
- Promise.all()
- 用于将多个Promsie实例,包装成一个新的Promise 实例
- 新的Promise实例的状态由其中每一个Promise来决定
1) 如果每一个Promise的状态都为fulfilled,新的Promise实例的状态为fulfilled,每一个Promise的返回值形成一个数组,传递给新的Promise实例的回调函数
const sendAjax = (url) => {
return new Promise((resolve, reject) => {
let xhr = new XMLHttpRequest();
xhr.open("GET", url);
xhr.send();
xhr.responseType = "json";
xhr.onreadystatechange = () => {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
resolve(xhr.response);
} else {
reject(xhr.status);
}
}
};
});
};
const p1 = sendAjax("url"); // 此url应为可访问的接口地址
const p2 = sendAjax("url"); // 此url应为可访问的接口地址
Promise.all([p1, p2])
.then((res) => {
console.log(res);
})
.catch((err) => {
console.log(err, "err");
});
2) 如果其中有一个Promise的状态为rejected,则新的Promise实例的状态为rejected,第一个被rejected的返回值,传递给新的Promise实例的回调函数
const p3 = sendAjax("url"); // 此url应为可访问的接口地址
const p4= new Promise((resolve, reject) => {
reject(new Error("p4的Promise状态为rejected"));
});
const p5 = new Promise((resolve, reject) => {
reject(new Error("p5的状态为rejected"));
});
Promise.all([p3, p4, p5])
.then((res) => {
console.log(res);
})
.catch((err) => {
console.log(err, "err");
});
每个 promise状态均为fulfilled时,且有自己then方法时
const p1 = new Promise((resolve, reject) => {
resolve("p1");
})
.then((res) => {
console.log(res, "res1");
return res
})
.catch((err) => {
console.log(err, "err1");
});
const p2 = new Promise((resolve, reject) => {
resolve("p2");
})
.then((res) => {
console.log(res, "res2");
})
.catch((err) => {
console.log(err, "err2");
});
const p3 = new Promise((resolve, reject) => {
resolve("p3");
})
.then((res) => {
console.log(res, "res3");
})
.catch((err) => {
console.log(err, "err3");
});
Promise.all([p1,p2,p3]).then(res=>{
console.log(res,'resNew');
}).catch(err=>{
console.log(err,'errNew');
})
实例状态中含有rejected,且每个rejected状态的实例有自己的catch方法时,不会调用新实例的catch方法
const p1 = new Promise((resolve, reject) =
resolve("p1");
})
.then((res) => {
console.log(res, "res1");
return res
})
.catch((err) => {
console.log(err, "err1");
});
const p2 = new Promise((resolve, reject) =
reject("p2");
})
.then((res) => {
console.log(res, "res2");
})
.catch((err) => {
console.log(err, "err2");
});
const p3 = new Promise((resolve, reject) =
resolve("p3");
})
.then((res) => {
console.log(res, "res3");
})
.catch((err) => {
console.log(err, "err3");
});
Promise.all([p1,p2,p3]).then(res=>{
console.log(res,'resNew');
}).catch(err=>{
console.log(err,'errNew');
})
- Promise.race()
- 将多个 Promise 实例,包装成一个新的 Promise 实例
- 每个Promise实例,有一个先改变状态新的Promise实例就会改变状态,且将最先改变状态的实例的的返回值,传递给新Promise实例的回调函数
const p1 = new Promise((resolve,
setTimeout(() => {
resolve("p1");
},3000);
});
const p2 = new Promise((resolve,
setTimeout(() => {
resolve("p2");
}, 2000);
});
const p3 = new Promise((resolve,
setTimeout(() => {
resolve("p3");
}, 1000);
});
Promise.race([p1, p2, p3])
.then((res) => {
console.log(res, "newRes");
})
.catch((err) => {
console.log(err, "newErr");
});