Promise

1,600 阅读2分钟

一 为什么要使用Promise

由于异步任务不能直接拿到结果,于是我们传一个回调(函数)给异步任务,当异步任务完成时调用回调,同时调用的时候把异步任务的结果作为回调的参数。但是该方法容易出现回调地狱,代码变得使人看不懂,因此使用Promise。

二 用法

//该bool用来帮助模拟成功或失败
let bool=false
//封装Promise
let fn=()=>{
    //返回promise实例
    return new Promise((resolve,reject)=>{
        if(bool){
            //成功执行resolve
            resolve('成功');
        }else{
        	//失败执行reject
            reject('失败');
        }
    })
}
//注意,成功和失败的回调函数都只能接收一个参数
fn().then(data=>console.log(data),error=>console.log(error))
//bool为false,则执行失败的回调,回调的参数error的值为"失败"

三 Promise的其他API

  1. Promise.resolve(result)
//制造一个成功或失败
Promise.resolve(1).then(value=>console.log(value))
Promise.resolve(new Promise((resolve,reject)=>reject('制造失败'))).then(null,error=>console.log(error))

  1. Promise.reject(reason)
//制造一个失败
Promise.reject(2).then(value=>console.log(value),error=>console.log('失败'))

  1. Promise.all(array)
//等待全部成功,或者有一个失败
Promise.all([Promise.reject('err1'),Promise.resolve(1)])
	.then(value=>console.log(value),error=>console.log(error))
Promise.all([Promise.resolve(1),Promise.reject('err2')])
	.then(value=>console.log(value),error=>console.log(error))
Promise.all([Promise.resolve(1),Promise.resolve(2)])
	.then(value=>console.log(value),error=>console.log(error))
Promise.all([Promise.reject('err3'),Promise.reject('err4')])
	.then(value=>console.log(value),error=>console.log(error))

  1. Promise.race(array)
//等待第一个状态改变
Promise.race([Promise.reject('err1'),Promise.resolve(1)])
	.then(value=>console.log(value),error=>console.log(error))
Promise.race([Promise.resolve(1),Promise.reject('err2')])
	.then(value=>console.log(value),error=>console.log(error))
Promise.race([Promise.resolve(1),Promise.resolve(2)])
	.then(value=>console.log(value),error=>console.log(error))
Promise.race([Promise.reject('err3'),Promise.reject('err4')])
	.then(value=>console.log(value),error=>console.log(error))

  1. Promise.allSettled(array)
//all只要有一个失败就中断,但我们希望拿到所有结果
//allSettled等待全部promise状态改变
Promise.allSettled([Promise.reject('err1'),Promise.resolve(1)])
	.then(value=>console.log(value),error=>console.log(error))
//自己模拟实现Promise.allSettled
Promise.allSettled2=(promiseList)=>{
    return Promise.all(promiseList.map(promise=>promise.then((value)=>{return {status:"ok",value}},(value)=>({status:"not ok",value}))))
}

三 手写Promise.all

function all(promiseArray){
    return new Promise((resolve,reject)=>{
        if(!Array.isArray(promiseArray)){
            return reject(new Error('传入的参数必须是数组'));
        }
        let res=[];
        let counter=0;
        for(let i=0;i<promiseArray.length;i++){
            Promise.resolve(promiseArray[i]).then(value=>{
                counter++;
                res[i]=value;
                if(counter===promiseArray.length){
                    return resolve(res);
                }
            }).catch(
                e=>{
                    reject(new Error('失败'));
                }
            )
        }
    })
}

var promise1 = Promise.resolve(3);
var promise2 = new Promise(function(resolve, reject) {
  setTimeout(resolve, 100, 'foo');
});
var promise3 = 42;

Promise.all([promise1, promise2, promise3]).then(function(values) {
  console.log(values);
});

四 手写Promise.race

function race(promiseArray){
    return new Promise((resolve,reject)=>{
        if(!Array.isArray(promiseArray)){
            return reject(new Error('传入的参数必须是数组'));
        }
        for(let i=0;i<promiseArray.length;i++){
            Promise.resolve(promiseArray[i]).then(value=>{
                resolve(value)
            }).catch(
                e=>{
                    reject(new Error('失败'));
                }
            )
        }
    })
}

var promise1 = Promise.resolve(3);
var promise2 = new Promise(function(resolve, reject) {
  setTimeout(resolve, 100, 'foo');
});
var promise3 = 42;

Promise.race([promise1, promise2, promise3]).then(function(values) {
  console.log(values);
});