天天看点

JavaScript异步编程Promise

再次梳理一下同步和异步的区别:

同步:在执行一段代码,没有返回结果之前,则不执行后面的代码。会阻塞后面代码的执行。

异步:与同步执行相反,在执行执行一段代码没有返回结果时,通过一个回调函数来处理这个结果,继续执行后面的代码。

在ES6中,用Promise对象来表示异步的最终完成和结果。

Promise以下三个状态:

待定(pending): 初始状态。

已兑现(fulfilled): 意味着操作成功完成。

已拒绝(rejected): 意味着操作失败。

pending状态要么转化为fulfilled,要么转化为rejected状态,通过promise的then方法和catch方法来返回对应的promise对象。

const fs = require("fs")

let readFilePromise = (filename) => {
    return new Promise((resolve,) => {
        fs.readFile(filename, (err,) => {
            if (err) {
                reject(err)
            } else {
                resolve(data)
            }
        })
    })
}
readFilePromise('./fs.json').then(res => {
    console.log("res", res)
})      

每次任务执行结束后产生的失败是直接被catch捕捉到的,因为Promise采用的是错误冒泡的方式,产生的错误会一直往后传递,直到被catch捕获。这样我们就不用频繁的检查错误了。

这就是Promise的好处:通过链式调用的方式来解决了多层嵌套的问题;Promise通过错误冒泡来统一做错误处理,这样避免每个任务都要错误检查导致代码混乱的问题。

Promise静态方法

Promise.all

参数是可迭代的对象,比如数组,Promise.all是把多个异步操作并行执行,所有的异步都成功后才返回成功,返回的值也是按照入参的顺序来返回。如果有一个异步失败,就返回失败,会把第一个异步失败当成Promise.all的失败结果返回。

//1.获取轮播数据列表

function getBannerList() {

    return new Promise((resolve,) => {

        setTimeout(function () {

            resolve('banner')

        }, 300)

    })

}

//2.获取店铺列表

function getStoreList() {

    return new Promise((resolve,) => {

        setTimeout(function () {

            resolve('store')

        }, 500)

    })

}

//3.获取分类列表

function getCategoryList() {

    return new Promise((resolve,) => {

        setTimeout(function () {
            reject("失败了")
            // resolve('category')

        }, 700)

    })

}

function initLoad() {

    Promise.all([getBannerList(), getStoreList(), getCategoryList()])

        .then(res => {

            console.log(res)

        }).catch(err => {

            console.log(err)

        })

}

initLoad()      

Promise.allSettled

和Promise.all相似,返回一个对象数组,每个对象表示对应的异步任务的结果,不管异步任务的结果fulfilled还是reject。

Promise.allSettled适合多个彼此不依赖的异步任务,Promise.all更合适多个相互依赖的异步任务。

对之前的案例代码稍微改造一下:

function initLoad() {

    Promise.allSettled([getBannerList(), getStoreList(), getCategoryList()])

        .then(res => {

            console.log(res)

        }).catch(err => {

            console.log(err)

        })

}

initLoad();  // [{ status: 'fulfilled', value: 'banner' },{ status: 'fulfilled', value: 'store' },{ status: 'rejected', reason: '失败了' }]      

Promise.any

传入一个可迭代的参数,如数组。

返回已经成功的异步任务,如果有多个异步都fulfilled了的,那就返回第一个。如果所有的参数都变成rejected的话,那么就返回一个rejected。

//1.获取轮播数据列表

function getBannerList() {

    return new Promise((resolve,) => {

        setTimeout(function () {

            reject('banner')

        }, 300)

    })

}

//2.获取店铺列表

function getStoreList() {

    return new Promise((resolve,) => {

        setTimeout(function () {

            reject('store')

        }, 500)

    })

}

//3.获取分类列表

function getCategoryList() {

    return new Promise((resolve,) => {

        setTimeout(function () {
            reject("失败了")
            // resolve('category')

        }, 700)

    })

}

function initLoad() {

    Promise.any([getBannerList(), getStoreList(), getCategoryList()])

        .then(res => {

            console.log(res)

        }).catch(err => {

            console.log(err)

        })

}
initLoad(); // [AggregateError: All promises were rejected]      

Promise.race

继续阅读