JavaScript异步编程--Promise

Promise

一种更优的异步编程统一方案,可是直接使用传统回调方式去完成复杂的异步流程会形成大量的回调问题(回调地狱),CommonJS社区提出了Promise的规范,目的就是为异步编程提供更合理更规范的统一解决方案,在ES2015中被标准化,成为语言规范。javascript

Promise就是一个对象,用来表示一个异步任务最终结束以后到底是成功仍是失败,就像是内部对外界作出了一个承诺,一开始这个承诺是待定的状态(pending),最终有多是成功(Fulfilled)对应的回调函数为onFulfilled,也多是失败(Rejected)对应的回调函数为onRejected。java

示例:node

// Promise接收一个函数,函数有两个参数(都是函数),resolve和reject
    const promise = new Promise(function (resolve, reject) {
        // resolve函数的做用就是把Promise的状态修改成Fulfilled
        // 成功的结果就是经过这个resolve传递出去
        resolve(100)
        
        // reject函数的做用就是把Promise的状态修改成Rejected
        // 失败的结果经过这个reject传递出去
        // reject传递的参数通常是一个错误对象,描述错误的缘由
        reject(new Error('promise rejected'))
    })
    
    promise.then(function(value) {
        // 当返回resolve时会调用这个回调函数
        console.log('resolve', value) // => 100
    }, function(err) {
        // 当返回reject时会调用这个回调函数
        console.log('rejected', err) // => Error对象
    })
复制代码

Promise链式调用

  • Promise对象的then方法会返回一个全新的Promise对象
  • 后面的then方法就是在为上一个then返回的Promise注册回调
  • 前面then方法中回调函数的返回值会做为后面then方法回调的参数
  • 若是回调中返回的是Promise,那后面then方法的回调会等待它的结束

Promise的异常处理

onRejected是为Promise中的异常作一些处理,如:Promise主动调用reject方法、调用一个不存的方法、主动抛出一个Error异常。ajax

经过Promise的catch方法捕获异常编程

promise.then(function(value) {
        // 当返回resolve时会调用这个回调函数
        console.log('resolve', value) // => 100
    })
    .catch(function(err) { // catch方法其实就是reject方法的一个别名
        // 当返回reject时会调用这个回调函数
        console.log('rejected', err) // => Error对象
    })
复制代码

catch不then方法第二个参数捕获异常的不一样点:json

  • catch捕获的是上一个then方法出现的异常
  • then方法第二个参数捕获的是当前Promise出现的异常

若是在Promise链条中发生异常,这个异常会被一直日后传递,直到被捕获,因此catch方法更像是给整个链条注册的异常捕获。api

Promise的静态方法

resolve方法直接将值返回数组

示例:promise

Promise.resolve('foo')
        .then(function(value) {
            console.log(value) // => foo
        })
    
    // 上边获得的value就和下边这种同样
    new Promise(function(resolve, reject) {
        resolve('foo')
    })
复制代码

使用Promise对象的静态方法resolve包装一个Promise,获得的是本来被包装的Promise 示例:异步

let promise = ajax('/api/users.json')
    let promise2 = Promise.resolve(promise)
    console.log(promise === promise2) // => true
复制代码

Promise的resolve方法返回一个带有then方法的对象,这个对象也具备onFulfilled方法时,咱们也能够经过then方法拿到返回的值 示例:

Promise.resolve({
        then: function(onFulfilled, onRejected) {
            onFulfilled('foo')
        }
    })
    .then(function(value) {
        console.log(value) // => foo
    })
复制代码

与resolve静态方法对应的是reject静态方法,reject静态方法返回就是错误信息,使用上和resolve相似,如:Promise.reject(new Error('xxx'))

Promise并行执行

Promise.all

当有多个异步任务须要同时处理时,在以前是经过定义一个计数器的形式来判断全部异步任务是否都执行完成。在Promise中如今给咱们提供了一个能够同时处理多个异步任务的方法:all。

示例:

let promise = Promise.all([
        ajax('/api/users.json'),
        ajax('/api/posts.json')
    ])
    
    // all方法会当全部异步任务都执行完成以后返回一个Promise对象
    // 只有当全部异步任务都成功时才返回resolve,不然返回reject
    peomise.then(function(value) {
        // value传递的为一个数组,数组中包括全部异步任务的执行结果
        console.log(value) // => [xx, xx]
    })
复制代码

Promise.race

race方法也一样能够将多个Promise对象组合为一个全新的Promise对象,与all方法不一样的是all方法等待全部异步任务结束以后结束;race方法是只会等待第一个异步任务结束后结束,也就是只要其中任何一个异步任务完成以后race方法就会结束。

示例:

const request = ajax('/api/posts.json')
    const timer = new Promise((resolve, reject) => {
        setTimeout(() => reject(new Error('timeout')), 500)
    })
    
    Promise.race([
        request,
        timer
    ])
    .then(value => {
        // 若是500ms之内request方法成功则执行成功的回调
        console.log(value)
    })
    .catch(err => {
        // 若是500ms之内request方法没有成功,则执行失败的回调
        console.log(err)
    })
复制代码

Promise执行时序

回调队列中任务一般被称做宏任务,宏任务执行过程当中可能会添加一些额外的需求,新添加的需求能够选择做为一个新的宏任务进入到队列中排队,例如setTimeout会在宏任务中排队,也能够做为一个微任务,直接在当前任务结束以后当即执行。 Promise的回调做为微任务执行,在本轮调用结束的末尾当即执行。 微任务:为了提升总体的响应能力 目前绝大多数异步调用都是做为宏任务执行,而Promise对象、MutationObserver、node中的process.nextTick是做为微任务执行

示例:

console.log('begin')
    
    // 做为宏任务执行
    setTimeout(() => {
        console.log('timer')
    }, 0)
    
    // 做为微任务执行
    Promise.resolve()
        .then(() => {
            console.log('promise')
        })
        .then(() => {
            console.log('promise2')
        })
        
    console.log('end')
    
    // => begin => end => promise => promise2 => timer
复制代码
相关文章
相关标签/搜索