什么是Promise
Promise 是一个构造函数,自身具有all, allSettled, resolve,reject, race 等方法,原型上有then, catch, finally等方法(因此我们通过 Promise 构造函数实例化的 实例仍然具有这些方法)
console.log(Promise)
-------------------------------------
ƒ Promise()
> all: ƒ all()
> allSettled: ƒ allSettled()
> any: ƒ any()
> arguments: (...)
> caller: (...)
> length: 1
> name: "Promise"
> prototype: Promise
catch: ƒ catch()
constructor: ƒ Promise()
finally: ƒ finally()
then: ƒ then()
Symbol(Symbol.toStringTag): "Promise"
__proto__: Object
> race: ƒ race()
> reject: ƒ reject()
> resolve: ƒ resolve()
> Symbol(Symbol.species): (...)
> Symbol(allSettled): ƒ (d)
> get Symbol(Symbol.species): ƒ [Symbol.species]()
> __proto__: ƒ ()
> [[Scopes]]: Scopes[0]
Promise基本用法
then & catch
function getNumber(){
var p = new Promise(function(resolve, reject){
//做一些异步操作
setTimeout(function(){
var num = Math.ceil(Math.random()*10); //生成1-10的随机数
if(num<=5){
resolve(num);
}
else{
reject('数字太大了');
}
}, 2000);
});
return p;
}
// 写法一
getNumber() // 函数执行返回一个Promise对象
.then(
function(data){ // resolve 函数, 异步任务执行成功的回调
console.log('resolved');
console.log(data);
},
function(reason, data){ // reject 函数, 异步任务执行失败的回调
console.log('rejected');
console.log(reason);
}
);
// 写法二
getNumber()
.then(function(data){ // resolve 函数, 异步任务执行成功的回调
console.log('resolved');
console.log(data);
})
.catch(function(data){ // reject 函数, 异步任务执行失败的回调
console.log('rejected');
console.log(reason);
})
all的用法
Promise的all方法提供了并行执行异步操作的能力,并且在所有异步操作执行完后才执行回调
有了all,你就可以并行执行多个异步操作,并且在一个回调中处理所有的返回数据,一些游戏类的素材比较多的应用,打开网页时,预先加载需要用到的各种资源如图片、flash以及各种静态文件。所有的都加载完后,我们再进行页面的初始化。
function runAsync1(){
let p1 = new Promise(function(resolve, reject){
// 执行一些异步任务
setTimeOut(function(){
console.log('异步任务1执行完成');
resolve('随便什么数据1')
}, 2000)
})
return p1;
}
function runAsync2(){
let p1 = new Promise(function(resolve, reject){
// 执行一些异步任务
setTimeOut(function(){
console.log('异步任务2执行完成');
resolve('随便什么数据2')
}, 2000)
})
return p2;
}
function runAsync3(){
let p1 = new Promise(function(resolve, reject){
// 执行一些异步任务
setTimeOut(function(){
console.log('异步任务3执行完成');
resolve('随便什么数据3')
}, 2000)
})
return p3;
}
// 接受三个异步执行的函数,三个异步操作的并行执行的,等到它们都执行完后才会进到then里面
Promise.all([runAsync1(), runAsync2(), runAsync3()]).then((result)=>{
console.log(result);
// 异步任务1执行完成
// 异步任务2执行完成
// 异步任务3执行完成
// ["随便什么数据1", "随便什么数据2", "随便什么数据3"]
})
race的用法
谁跑的快,以谁为准执行回调
多个异步任务同时执行,如果有一个任务执行完成,执行回调函数,后续的任务正常执行,不在打印回调结果
function runAsync1(){
let p1 = new Promise(function(resolve, reject){
// 执行一些异步任务
setTimeOut(function(){
console.log('异步任务1执行完成');
resolve('随便什么数据1')
}, 2000)
})
return p1;
}
function runAsync2(){
let p1 = new Promise(function(resolve, reject){
// 执行一些异步任务
setTimeOut(function(){
console.log('异步任务2执行完成');
resolve('随便什么数据2')
}, 2000)
})
return p2;
}
function runAsync3(){
let p1 = new Promise(function(resolve, reject){
// 执行一些异步任务
setTimeOut(function(){
console.log('异步任务3执行完成');
resolve('随便什么数据3')
}, 2000)
})
return p3;
}
Promise.race([runAsync1(), runAsync2(),runAsync3()]).then((result)=>{
console.log(result);
// 异步任务1执行完成
// 随便什么数据1
// 异步任务2执行完成
// 异步任务3执行完成
})
使用场景
可以用race给某个异步请求设置超时时间,并且在超时后执行相应的操作
请求图片任务、超时5s任务 两个任务 执行Promise.race() 如果超过5s图片任务还没有请求图片,则执行超时任务提升超时
function getImg(){
let p = new Promise(function(resolve, reject){
let img = new Image();
img.onload = function(){
resolve(img)
}
img.src = 'https://cdn.nlark.com/yuque/0/2020/png/152077/1606703278597-fdcaa8e1-3394-463a-bac2-c2dcfa3df160.png';
})
return p;
}
function timeout(){
let p = new Promise(function(resolve, reject){
setTimeout(function(){
reject('图片超时了')
}, 5000)
})
return p;
}
Promise.race([getImg(), timeout()]).then(function(data){
console.log(data);
}).catch(function(error){
console.log(error);
})
参考
- 大白话讲解Promise(一)
- 大白话讲解Promise(二)理解Promise规范
- Promise A+ 规范
- JavaScript Promise迷你书(中文版)
- ES6 Promise
- 手写Promise https://juejin.cn/post/6844903843507994632