您现在的位置是:首页 >学无止境 >Promise是什么?网站首页学无止境
Promise是什么?
目录
Promise是异步编程的一种解决方案,它就是一个容器,里面保存着某个未来才会结束的事件的结果,从语法上说,Promise就是一个对象,从他可以获取异步操作的消息。
Promise对象的特点
-
对象的状态不受外界的影响:Promise对象代表一个异步操作,有三种状态:pending、fullfilled、rejected,只有异步操作的结果可以决定当前是哪一种状态,任何其他操作都无法改变这个状态
-
一旦改变,就不会再变,任何时候都可以得到这个结果
Promise.resolve()
将现有对象转为Promise对象。
Promise.resolve('foo')
//等价于
new Promise(resolve=>resolve('foo'))
参数:
-
是一个Promise实例
如果参数是Promise实例,那么Promise.resolve将不做任何修改,原封不动地返回这个实例。 -
是一个thenable对象
thenable对象指的是具有then方法的对象,如:
let thenable={
then:function(resolve,reject){
resolve(42)
}
}
Promise.resolve方法会将这个对象转为Promise对象,然后就立即执行thneable对象的then方法
3.不是具有then方法的对象,或根本就不是对象
Promise.resolve方法返回一个新的Promise对象,状态为resolved。
const p=Promise.resolve('hello')
p.then((s)=>{
console.log(s)
})
4.不带有任何参数
Promise.resolve()方法允许调用时不带参数,直接返回一个resolved状态的Promise对象。
如果希望得到一个Promise对象,比较方便的方法就是直接调用Promise.resolve()方法,如下:
const p=Promise.resolve();
p.then(()=>{
//...
})
立即resolve()的Promise对象,是在本轮“事件循环”(event loop)的结束时执行,而不是在下一轮“事件循环”的开始时。
setTimeout(function () {
console.log('three');
}, 0);
Promise.resolve().then(function () {
console.log('two');
});
console.log('one');
// one
// two
// three
js的执行顺序:先同步再异步。
异步中任务队列的执行顺序:先微任务队列,再宏任务队列。
Promise中的resolve、reject属于微任务队列,settimeout属于宏任务队列。
Promise.reject()
Promise.reject(reason)方法也会返回一个新的Promise实例,该实例的状态是rejected
const p=Promise.reject('出错了')
//等价于
const p=new Promise((resolve,reject)=>{
reject("出错了")
})
p.then(null,(s)=>{
console.log(s)//出错了
})
Promise.reject()方法的参数,会原封不动地作为reject的理由,变成后续方法的参数。
const thenable={
then(resolve,reject){
reject("出错了")
}
}
Promise.reject(thenable)
.catch(e=>{
console.log(e===thenable)//true
})
Promise.try()
让同步函数同步执行,异步函数异步执行,并让它们具有统一的·API
有两种写法:
-
async函数
const f=()=>console.log('now')
(async()=>f())()//同步函数写法
(async()=>f())().then(...)//异步函数写法
console.log('next')
//now
//next
2.new Promise()
const f=()=>console.log('now')
(
()=>new Promise(resolve=>resolve(f()))
)()
cosole.log('next')
//now
//next
-
上面代码使用的是立即执行的匿名函数,执行new Promise(),这种情况下,同步函数也是同步执行的。
-
还可以用Promise.try方法代替上面的写法:
const f=()=>console.log('now')
Promise.try(f)
console.log('next')
//now
//next
-
还可以统一用peomise.catch()捕获所有同步和异步的错误:
Promise.try(() => database.users.get({id: userId}))
.then(...)
.catch(...)
Promise.all()
Promise.all()方法用于将多个Promise实例,包装成一个新的Promise实例。
const p=Promise.all([p1,p2,p3])
-
Promise.all()的参数可以不是数组,但必须有Iterator接口,且返回的每个成员都是Pomise实例
-
p的状态由p1、p2、p3决定,分成两种情况
-
只有p1、p2、p3的状态都变成fullfilled,p的状态才会变成fullfilled,此时p1、p2、p3的返回值组成一个数组,传递给p的回调函数
-
只要p1、p2、p3之中有一个被rejected,p的状态就变成rejected,此时第一个被reject的实例的返回值,会传递给p的回调函数
-
const databasePromise = connectDatabase();
const booksPromise = databasePromise
.then(findAllBooks);
const userPromise = databasePromise
.then(getCurrentUser);
Promise.all([
booksPromise,
userPromise
])
.then(([books, user]) => pickTopRecommendations(books, user));
注意:如果参数中有Promise实例并且自己定义了catch方法,那么它一旦被rejected,并不会触发Promise.all()的catch方法.
Promise.race()
Promise.race()方法同样是将多个Promise实例,包装成一个新的Promise实例
const p=Promise.race([p1,p2,p3])
上面代码中,只要p1、p2、p3之中有一个实例率先改变状态,p的状态就跟着改变,率先改变的Promise实例的返回值传递给p的回调函数。
Promise.all()方法的参数与Promise.all()方法的一样,如果不是Promise实例,就会先调用Promise.resolve方法,将参数转为Promise实例。
const p = Promise.race([
fetch('/resource-that-may-take-a-while'),
new Promise(function (resolve, reject) {
setTimeout(() => reject(new Error('request timeout')), 5000)
})
]);
p
.then(console.log)
.catch(console.error);
上面代码中race有两个参数:fetch('/resource-that-may-take-a-while')和new Promise(function (resolve, reject) { setTimeout(() => reject(new Error('request timeout')), 5000) }),如果在5秒之内第一个函数没有返回结果,就会因为执行第二个函数,导致Promise的状态变为reject。
Promise.allSettled()
Promise.allSettled()方法接受一组Promise实例作为参数,包装成一个新的Promise实例,只有等到所有这些参数实例都返回结果,不管是fullfilled还是rejected,包装实例才会结束。当我们不关心异步操作的结果,只关心这些操作有没有结束,这时,Promise.allSettled()方法就派上用场了。
Promise.any()
Promise.any()方法接收一组Promise实例作为参数,包装成一个新的Promise实例,只要有一个参数实例变成fullfilled状态,包装实例就会变成fullfilled状态,如果所有参数实例都变成rejected状态,包装实例就会变成rejected状态,Promise的状态总是fullfilled。
区分易混淆:
在这里我们区分一下Promise.all()、Promise.race()、Promise.allSettled()、Promise.any():
-
Promise.all():参数实例状态都变成fullfilled,Promise的状态才会变成fullfilled,只要有一个变成rejected,Promise的状态就会变成rejected。
-
Promise.race():参数实例率先改变状态的,Promise的状态会跟着改变。
-
Promise.allSettled():当参数实例发出的请求结束时,不管其是fullfilled还是rejected,Promise的状态总是fullfilled
-
Promise.any():只要有一个参数实例变成fullfilled,Promise状态就会变成fullfilled,如果所有参数实例状态都变成rejected状态,Promise状态就会变成rejected
文档:ES6 入门教程