Promise的使用

216 阅读6分钟

1.Promise

promise 是ES6新增异步解决方案

Promise generator ===> ES7 async/await

Promise(承诺) 表示未来的某个时间一定会返回一个承诺的结果给你

Promise 是一个容器,里面包裹了一些异步操作,它表示一个预计会在未来完成的异步操作

Promise有三种状态: pending(进行中) fulfilled(已成功) rejected(已失败)

Promise接受一个函数做为参数,这个回调函数有两个参数:这两个回调函数只要没有调用就一直是pendding的状态(这两个回调函数一个是 resolve成功后的回调函数 一个是 reject失败后的回调函数)

Promise状态变化pending =>fulfilled 或者 pending=>rejected 且不可逆的,而且一旦执行成功状态就会凝固,会一直保持这个状态,不会在发生其他变化了

Promise状态一旦发生改变就会触发promise的then方法,then方法中有两个默认回调函数,一个是成功后的回调resolve,一个是失败后的回调reject

Promise实例上 有三个api

then(resolve=>{},reject=>{}) 方法中有两个回调函数 分别表示成功后的回调 和失败后的回调

catch(err=>{}) 在创建或者使用promise的时候,如果代码报错那么会自动的走then.reject 如果在then中没有reject回调,会在catch中进行错误捕获, catch方法也会捕获在then方法中发生任何错误

finally(()=>{}) 无论promise执行成功或者失败,也无论catch方法是否执行, 最终finally都会执行

1.一旦promise创建成功就会立即执行(new Promise())

console.log(1);
let p1=new Promise((resolve,reject)=>{
        resolve('1') //成功后的回调
        reject('2')//失败后的回调
        console.log(2);
})	
console.log(p1); //Promise
p1.then((resolve)=>{//异步操作
        // resolve 成功后的结果
        console.log(3);
        console.log("resolve 成功后的结果",resolve);//1
        //如果成功则不会走reject
},(reject)=>{
        // reject失败后的结果
        console.log("reject 失败后的结果",reject);//2
})
console.log(4);

上述代码中他们的打印数字顺序是1243,代码从上往下执行,promise里面是同步的,它的then方法是异步的所以放在了最后。

promise的手动报错的方法: throw new Error("手动报错"),打上这个代码手动报错后就会走reject或者catch方法

2.promise错误捕获 catch

在创建或者使用promise的时候,如果代码报错那么会自动的走then.reject 如果在then中没有reject回调,会在catch中进行错误捕获, catch方法也会捕获在then方法中发生任何错误

let p1=new Promise((resolve,reject)=>{
        if(1<0){
                resolve(1)
        }else{
                reject(2)
        }
})
p1.then((resolve)=>{
        throw new Error('手动报错')
        console.log('resolve 成功后的结果', resolve);
}).catch((err)=>{
        console.log("catch err==>",err);
})
//返回结果是:catch err==> 2

3.promise.finally方法

无论promise执行成功或者失败,也无论catch方法是否执行, 最终finally都会执行

let p1=new Promise((resolve,reject)=>{
    if(1>0){
        throw new Error('手动报错')
        resolve(1)
    }else{
        reject(2)
    }
})
p1.then((resolve)=>{
      console.log('resolve 成功后的结果',resolve);
},(reject)=>{
      console.log("reject 失败后的结果",reject);
}).catch(err=>{
      console.log("catch err==>",err);
}).finally(()=>{
      console.log("finally fin===>");
})
//此时会走reject打印:'reject 失败后的结果 Error: 手动报错'
//同时会走finally打印: finally fin===>

2.Promise的API:应用程序接口

1.Promise.resolve

2.Promise.reject

3.Promise.all(): 如果都成功就正常返回,如果有一个失败,那么都会认为是失败的

Promise.all方法 参数是多个promise对象组成的数组, 返回值是一个新的promise对象

如果参数中的promise对象都成功就正常返回,并且promiseAll方法中的每一个promise都是并行状态,当全部完成之后就会自动的调用promise.all().then()方法.

如果参数中的promise对象有任意一个没有正常返回,那么整个pAll都会认为是失败的,并且把失败的这个promise对象的返回值直接输出 其他的就不会在继续执行了

let p1 = new Promise((resolve, reject) => {
    setTimeout(() => {//模拟异步
        resolve("p1")
    }, 1000)
});
        let p2 = new Promise((resolve, reject) => {
    setTimeout(() => {//模拟异步
        resolve("p2")
    }, 5000)
});
let p3 = new Promise((resolve, reject) => {
    setTimeout(() => {//模拟异步
        reject("p3")
    }, 2000)
});
let pAll = Promise.all([p1, p2, p3]);
        pAll.then( resolve => {
        console.log("成功后的回调",resolve);
        //"成功后的回调",["p1", "p2", "p3"]
    },
    reject => {
        console.log("失败后的回调",reject);
    })
//由于p3里面返回的是失败的,all方法就会走reject打印:失败后的回调 p3
//如果都是成功则all方法会走resolve打印:成功后的回调 (3) ["p1", "p2", "p3"]

4.Promise.race()

Promise.race方法返回的也是一个promise对象, race方法谁先有结果就返回谁,无论成功还是失败(成功的就走resolve,失败就会在reject中返回)

let p1 = new Promise((resolve, reject) => {
    setTimeout(() => {//模拟异步
        reject("p1")
    }, 1000)
});
let p2 = new Promise((resolve, reject) => {
    setTimeout(() => {//模拟异步
        resolve("p2")
    }, 5000)
});
let p3 = new Promise((resolve, reject) => {
    setTimeout(() => {//模拟异步
        resolve("p3")
    }, 2000)
});
let pRace = Promise.race([p1, p2, p3]);
pRace.then(
    resolve => {
        console.log("成功后的回调",resolve);//成功后的回调 p1
    },
    reject => {
        console.log("失败后的回调",reject);//失败后的回调 p1
    })
 //rece方法是谁先有结果先返回谁,由于p1时间最短所以会走reject打印:失败后的回调 p1

3.PromiseAPI和应用

1.promise.all方法

需求:有三张图片 ,如果这三张图片都加载完成 那么就直接显示到页面中 否则就不展示

var imgSrc1 = '1.jpg'
var imgSrc2 = '2.jpg'
var imgSrc3 = '3.jpg'

var imgBox = document.getElementById('imgBox')
var loadImg = (arg) => {
    return new Promise((resolve,reject)=>{
        // 配置定时器,用来看管是否在一定时间内完成,如果没有就报超时
        setTimeout(() => {
                reject('超時')
        }, 5000);
        // 如果一定时间内完成会走以下代码:
        // 创建一个img标签
        var img = document.createElement('img')
        // /当图片标签获得scr属性的时候,图片就开始被加载
        img.setAttribute('src',arg)
        // 当图片加载完成会触发这个onload回调函数
        img.onload = () => {
                resolve(img)
        }
    })
}
    

// 使用promise的api:all方法,调用三次加载图片函数 //如果都成功了,那么会返回成功后promise的resolve方法,如果有一个失败就会返回失败

   Promise.all([loadImg(imgSrc1),loadImg(imgSrc2),loadImg(imgSrc3)]).then(resolve=>{
            // resolve==> [图片1,图片2,图片3]
        for(var i = 0 ; i < resolve.length ; i++ ){
            // 将返回的img标签追加到元素中
                    imgBox.appendChild(resolve[i])
            }
        }).catch(err=>{
                    alert(err)
   })
            

2.promise.race方法

需求:有一张图片 ,当这张图片的加载时间超过1s的时候,就不去加载了,并且在页面中显示加载超时,如果1s内完成了加载,那么就在页面中进行展示

var loadingImg = (arg) => {
        var src = arg || '1.jpg'
        return new Promise((reslove,reject)=>{
                var img = document.createElement('img')//创建标签
                img.setAttribute('src',src)//给img标签添加src属性
                img.onload = () => {//图片加载完成会触发这个onload回调函数
                        reslove(img)
                }
        })
}
//设置timeOut函数方法
var timeOut = () => {
        //设置一个定时器
        return new Promise((reslove,reject)=>{
                setTimeout(()=>{
                        reject('图片加载超时')
                },2000)
        })
}

//使用promise.race方法来判断成功与否,如果2秒内成功就显示照片,否则显示图片超时
Promise.race([loadingImg(),timeOut()]).then(res=>{
        document.body.appendChild(res)
}).catch(err=>{
        alert(err)
})