Promise语法
Promise对象具有三种状态:
pending(进行中)
resolved(已成功)
rejected(已失败)
当promise的状态发生改变,让promise的回调函数进行回调队列(微队列),等待执行。
没有 promise 的时候,异步操作完成直接让自己的回调函数进入回调队列等待执行;有了 promise 的封装,异步操作执行完毕,改变 promise 的状态,promise 状态改变让 promise 的回调函数进入回调队列等待执行。所以,promise 就是中间商!
promise基本语法
①使用Promise构造函数创建promise对象
let p=new Promise(()=>{});
p就是创建的promise对象,初始状态是pending
Promise参数必须是一个回调函数
②修改promise对象的状态
//需要给Promise的回调函数传参
let p = new Promise((resolve,reject)=>{
resolve();//将promise对象状态变为resolved(fulfilled)
});
promise 对象的状态一旦改变,就不能在改变了。
Promise构造函数的参数是回调函数,是同步执行的,实例化过程就执行了
通过then方法给promise对象指定的回调函数是异步执行的,当promise的状态发生改变,这里的回调函数进入回调队列等待执行。
③指定promise对象的回调函数
let p=new Promsie((resolve,reject)=>{
//resolve和reject不论先调用谁,调用之后的状态都不会再发生改变
//调用resolve,把状态改为resolved,该参数会传递给then第一个回调函数
resolve([4,6,34,3]);
//调用reject把状态改为rejected,该参数回传给then的第二个回调函数
reject('连接超时...');
});
p.then((value)=>{
console.log(value);//[4,6,34,3]
},reason=>{
console.log(reason);//连接超时...
})
可以给promise指定两个回调函数,如果promise对象的状态是resolved,调用第一个回调函数,如果promise的状态是rejected,调用第二个回调函数;
Promise构造函数的回调函数中,调用resolve和reject的时候可以传递参数,promise对象的回调函数可以接收
Promise实例的方法
1. Promise.prototype.then()
①参数
then方法可以指定两个函数,都是回调函数,promise状态如果
是成功的调用第一个参数,promise对象如果是失败的,调用第二个参数
②返回值
then()方法一定会返回promise对象,所以then方法支持链式调用
then()方法返回值规则如下:
-
如果回调函数没有返回值,then()返回一个成功的promise对象,值是undefined。
-
如果回调函数指定返回值(且不是promise对象),then方法返回一个成功状态的promise对象,值是回调函数的返回值。
-
如果回调函数中抛出错误,then方法返回一个失败状态的promise对象,失败的reason是错误信息
-
如果回调函数是一个promise对象,返回值就是此promise对象
2.catch方法
①参数
参数指定一个回调函数,promise对象的状态变为失败的时候会调用
②then和catch可以配合使用
let p=new Promise((resolve,reject)=>{
reject('故意出错');
});
p.then(()=>{
console.log('成功');
}).catch(reason=>{
console.log('出错',reason);
})
③异常穿透
使用 then 进行链式调用的时候,可以只给then指定成功的回调函数,最后通过 catch 兜底,不论哪一步出现异常(状态变为失败),最终都会穿透到 catch ,执行它的回调函数。
function setTimeoutPromise(delay, value) {
// 创建 promise 对象并返回
return new Promise((resolve, reject) => {
setTimeout(resolve, delay, value);
});
}
setTimeoutPromise(2000).then(() => {
//取 0 -9 之间随机数
let rand1 = Math.floor(Math.random() * 10);
console.log(rand1);
a; // 异常语法
// 返回一个 promise 对象
return setTimeoutPromise(3000, rand1);
}).then(value => {
// 取随机数 + value
let rand2 = Math.floor(Math.random() * 10) + value;
console.log(rand2);
// 返回一个 promise 对象
return setTimeoutPromise(1000, rand2);
}).then(value => {
// 取随机数 + value
let rand3 = Math.floor(Math.random() * 10) + value;
console.log(rand3);
}).catch(reason => {
console.log('错误:', reason);
})
3.finally
接收一个回调函数作为参数,只要promise状态改变,回调函数就调用
Promise构造函数本身方法
1.Promise.resolve()
①功能
返回一个promise对象,可以用来快速创建一个promise对象
②根据参数不同返回的promise也不同
-
如果不给参数,返回一个成功状态的promise对象,值是undefined
-
如果给一个值作为参数(不是promise对象也不是thenable对象),返回一个成功状态的 promie 对象,值是参数。
-
如果参数是个 promise 对象,直接把这个 promise 对象作为返回值。
-
如果参数是一个thenable对象,方法内部会根据then方法创建一个有promise对象并返回
具有then方法的对象就是thenable对象
var obj={
then(resolve,reject){
reject('老子错了');
}
};
let p4=Promise.resolve(obj);
// 执行 resolve 方法的时候,内部实例化 Promise 构造函数,把 then 方法作为参数
2 Promise.reject()
没有 Promise.resolve 那么复杂,就返回一个失败状态的 promie 对象,参数不论是什么数据都会作为返回的promise对象失败原因;没有参数失败原因就是undefined。
3 Promise.all()
可以把多个promise对象整合成一个promise对象并返回
参数是一个数组或者其他可遍历对象,成员都是promise对象(不是promise对象的会自动使用Promise.resolve()创建为promise对象)
-
如果传入的所有的promise对象都是成功状态,则返回的promise对象会是所有promise对象的值组成的数组
-
一旦有一个 promise 对象变为失败状态,返回的 promise 对象立即变为失败状态!
Promise 的优势
-
回调函数设置方式更加灵活,可以设置多个,可以再任何时刻设置回调函数。
-
then 方法的链式调用,有效解决回调地狱问题 (回调地狱:回调函数内部嵌套回调函数)
宏队列和微队列
事件轮询机制中,回调队列有两个,分别是宏对列和微队列。
定时器的回调函数、DOM事件的回调函数、Ajax的回调函数会进入宏队列。
promise对象的回调函数进入微队列。