Promise

115 阅读3分钟

Promise

Promise是异步编程的解决方法 Promise有以下两个特点 1.Promise对象代表一个异步操作,有3种状态:Pending、Fulfilled和Rejected。只有异步操作的结果可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。 1、pending[待定]初始状态 2、fulfilled[实现]操作成功 3、rejected[被否决]操作失败

2.⼀旦状态改变就不会再变,任何时候都可以得到这个结果。 Promise对象的状态改变只有两种可能:从Pending变为Fulfilled和从Pending变为Rejected。只要这两种情况发⽣,状态就凝固了,不会再 变,⽽是⼀直保持这个结果,这时就称为Resolved(已定型)。

Promise构造函数接受⼀个函数作为参数,该函数的两个参数分别是resolve和reject。它们是两个函数,由JavaScript引擎提供,不⽤⾃⼰部署,他们的作用是将state从Pending变为fulfilled或者rejected

  • resolve函数的作⽤是:Pending--> Resolved,成功时调⽤,并将异步操作的结果作为参数传递出去;
  • reject函数的作⽤是,Pending--> Rejected,失败时调⽤,并将异步操作报出的错误作为参数传递出去。

then then ⽅法可以接受两个回调函数作为参数。成功回调和失败回调,其中,第⼆个函数是可选的,不⼀定要提供。这两个函数都接受Promise对象传出的值作为参数

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); //参数传出去了 由then方法第一个参数接收
            }
            else{
                reject('数字太大了');//参数传出去了 由then方法第二个参数和catch方法接收
            }
        }, 2000);
    });
    return p;            
}

getNumber()
then中的第一个参数时,如果抛出异常了,那么并不会报错卡死js,而是会进到catch方法中
.then(
    function(data){ 
        console.log('resolved');
        console.log(data);
    }, 
    function(reason, data){
        console.log('rejected');
        console.log(reason); //失败原因
    }

);
//等于
.catch(function(reason){
    console.log('rejected');
    console.log(reason);
});
  • Promise新建后会立即执行,
  • then方法指定的回调函数将在一步操作后执行

当Promise的状态发生了改变,不论是成功或是失败都会调用then方法。

Promise实例具有then方法,即then方法是定义在原型对象Promise.prototype上的。它的作用是为Promise实例添加状态改变时的回调函数并在异步完成时执行这个函数。

then方法返回的是一个新的Promise实例(注意,不是原来那个Promise实例)。因此可以采用链式写法,即then方法后面再调用另一个then方法。

基于上面的讨论我们很容易得出结论:

  • then方法可以在实例上调用。因此then 方法的实现是在Promise的 prototype上。
  • 他的作用是为Promise实例添加状态改变时的回调函数并在异步完成时执行这个函数
  • then方法会返回一个Promise,而且是返回一个新的Promise(详情)对象。
function runAsync1(){
    var p = new Promise(function(resolve, reject){
        //做一些异步操作
        setTimeout(function(){
            console.log('异步任务1执行完成');
            resolve('随便什么数据1');
        }, 1000);//时间最短执行最快
    });
    return p;            
}
function runAsync2(){
    var p = new Promise(function(resolve, reject){
        //做一些异步操作
        setTimeout(function(){
            console.log('异步任务2执行完成');
            resolve('随便什么数据2');
        }, 2000);
    });
    return p;            
}
function runAsync3(){
    var p = new Promise(function(resolve, reject){
        //做一些异步操作
        setTimeout(function(){
            console.log('异步任务3执行完成');
            resolve('随便什么数据3');
        }, 2000);
    });
    return p;            
}
runAsync1().then(data1 =>{
console.log(data1);
return runAsync2()
}).then(data2=>{console.log(data2)}).catch(err => console.log(err))

Promise all 并行执行异步操作的能力 所有异步操作执行完后才执行回调

Promise
.all([runAsync1(), runAsync2(), runAsync3()])
.then(function(results){
    console.log(results);
})

// ["函数数据11111", "随函数数据222222", "随便什么数据3333333"]

Promise race 哪个函数执行返回哪个 (可以用于获取图片,一个函数获取图片 一个函数计时 一定时间内没完成则返回计时函数 确认失败)

Promise
.race([runAsync1(), runAsync2(), runAsync3()])
.then(function(results){
    console.log(results);
})

微信图片_20210312105719.png

手写Promise加载图片

function loadImg(src) {
    const p = new Promise((resolve, reject) => {
        const img = document.createElement('img')
        img.onload = () => {
            resolve(img)
        }
        img.onerror = () => {
            const err = new Error(`图片加载失败 ${src}`)
            reject(err);
        }
        img.src = src;
    })
    return p;
}
var url1 = 'https://sghimages.shobserver.com/img/catch/2021/03/16/9dcb661d-2054-44e3-9e27-652e47d7fa33.jpg';
var url2 = 'https://sghimages.shobserver.com/img/catch/2021/03/16/0724999c-eae5-4946-aa7e-9f3d898e5336.jpg';


loadImg(url1).then((data1) => {
    console.log('第1张图片的宽度',data1.width);
    return data1;
}).then((data1) =>{
    console.log('第1张图片的高度',data1.height)
    return loadImg(url2);
}).then((data2) =>{
    console.log('第2张图片的宽度',data2.width);
}).catch((err) =>{
    console.log(err);
})