资讯专栏INFORMATION COLUMN

JavaScript之Promise

yck / 2035人阅读

摘要:的种状态对象一共有进行中,已成功和已失败种状态。如果执行成功,将返回一个数组,数组的值和实例的返回值一一对应。如果返回失败,会被自己的方法捕获,经过处理后返回一个成功的实例,返回值是失败状态返回的,最后也就返回成功状态。

写东西真是难啊,一是因为肚子里没多少货,二是因为掌握的东西也太细碎表面。好吧,这也是为什么要写的原因,希望能借此倒逼一下自己。

本来想着一个主题接一个主题的来写,但是发现好难。好吧,那就从自己熟悉的东西开始写。

Promise长啥样

先看大致的代码

new Promise(function (resolve, reject) {
  // 执行异步操作......

  // 判断异步操作的结果
  if (/* success */) {
    resolve(value);
  } else {
    reject(err);
  }
}).then(res => {
  // 成功,执行后续操作
}).catch(err => {
  // 失败,处理错误
})

Promise的字面意思就是承诺,承诺表示表示将要做但是还未做的事情,而且承诺还伴随着这件事情是成功或者失败的反馈。所以当new一个Promise的时候,就相当于告诉js引擎去帮我们执行一些操作(同步或者异步的都可以),执行完后再告诉我们结果,然后我们再根据结果的成功与否去做之后的操作。

举个栗子
console.log("start...")
new Promise(function (resolve, reject) {
  console.log("start promise...")
  // 大约0.5秒后执行
  setTimeout(() => {
    console.log("start timeout...")
    // 随机生成一个num,1 <= num <= 10
    const num = parseInt(Math.random() * 10) + 1
    // 大于5算成功,否则算失败
    if (num > 5) {
      resolve("success")
    } else {
      reject("failed")
    }
    console.log("end timeout...")
  }, 500)
  console.log("end promise...")
}).then(res => {
  console.log(res)
}).catch(err => {
  console.log(err)
})
console.log("end...")

运行结果:

start... 
start promise...
end promise...
end...
start timeout...
end timeout...
failed/success

这段代码,首先会打印出start...字符串,然后当我们new Promise()的时候,引擎会立刻执行Promise里的代码,所以打印出start promise...。紧接着,遇到setTimeout,所以直接跳到end priomise...处打印该字符串。这个时候,Promise里的代码暂时执行完毕,引擎将切换到Promise外部执行后续的同步代码,打印出end...。大约在0.5秒后,引擎将切回Primise内部执行setTimeout的回调函数,于是打印出start timeout...,但是不管resolve还是reject,只要没有return语句,都将打印出end promise...,最后才是执行then或者catch里的回调函数。

Promise的3种状态

Promise对象一共有pedding(进行中),fulfilled(已成功)和rejected(已失败)3种状态。从创建Promise到resolve函数执行之前,都是pedding状态,resolve()执行后变成fulfilled状态,reject()执行后变成rejected状态。

Promise的then方法

Promise的then方法是在Promise的状态改变时调用,接收两个参数,第一个参数是成功时的回调函数,第二个参数(可选)是失败时的回调函数。

then方法会返回一个新的Promise实例,于是我们可以继续在then后面写then(catch方法同样返回Promise实例,可以链式调用)。这个特性挺有用的,下面用示例说一下。

首先,先创建一个函数,该函数返回一个Promise实例,该Promise成功或失败的概率各50%。

const isMoreThanFive = function () {
  return new Promise(function (resolve, reject) {
    setTimeout(() => {
      const num = parseInt(Math.random() * 10) + 1
      if (num > 5) {
        resolve("success")
      } else {
        reject("failed")
      }
    }, 500)
  })
}

一个then函数的情况:

isMoreThanFive()
.then((res) => {
  console.log(res)
})
.catch(err => {
  console.log(err)
})
// 0.5秒后输出success或者failed

两个then函数的情况:

isMoreThanFive()
.then((res) => {
  console.log("first " + res);
  return isMoreThanFive()
})
.then(res => {
  console.log("second " + res);
})
.catch(err => {
  console.log(err)
})

这种情况,如果第一个isMoreThanFive执行失败,将直接执行catch回调,如果成功,会执行第一个then方法,then方法里又通过isMoreThanFive返回了一个新的Promise实例,这时,如果新的Promise成功将执行第二个then方法,如果失败将执行catch方法。

末尾的catch方法会捕获到前面Promise出现的所有异常,包括reject返回的失败状态和代码执行过程中发生的错误,所以一般会省略then方法的第二个参数(处理失败时的回调),而直接在最后添加catch方法统一处理前面发生的错误。
在调用接口时,如果B接口依赖A接口返回的参数,这时,then的链式调用将非常方便。

Promise的all方法

先看代码

const p1 = isMoreThanFive()
const p2 = isMoreThanFive()
Promise.all([p1, p2])
.then(res => {
  console.log(res)
})
.catch(err => {
  console.log(err)
})  
// 输出 failed 或者 ["success", "success"]

all方法接受一个数组,数组各项都是Promise实例。Promise.all会返回一个新的Promise实例,只有当数组内所有的Promise实例都成功时,all才返回成功状态,否则只要有一个失败都返回失败状态。如果all执行成功,将返回一个数组,数组的值和Promise实例的返回值一一对应。

注意,传给all方法的所有Promise实例都是同时执行的,也就是说同时执行多个异步操作,如果某个实例失败,则all方法直接返回失败状态,返回值由失败的Promise实例提供。

这在前端渲染页面时非常有用,利用Promise.all方法将可以同时请求多个接口,提升页面的渲染速度。

特殊情况,当Promise实例有自己的catch方法时:

const p1 = isMoreThanFive()
const p2 = isMoreThanFive()
          .catch(err => {
            return err
          })
Promise.all([p1, p2])
.then(res => {
  console.log(res)
})
.catch(err => {
  console.log(err)
})  
// 输出 failed 或者 ["success", "success"] 或者 [ "success", "failed" ]

如果传入的Promise实例有自己的catch方法,就不会触发Promise.all的catch方法。p2如果返回失败,会被自己的catch方法捕获,经过catch处理后返回一个resolved成功的Promise实例,返回值是失败状态返回的err,最后Promise.all也就返回成功状态。

最后

多带带使用Promise已经很方便很直观了,但是如果配合上async函数的话,写异步代码完全可以使用同步的写法,下一篇将会写关于async的东西。

关于Promise,大致就是这些,没有面面俱到,主要是把自己觉得经常用到的和重要的写了下来。如果想了解更多的细节和原理可以看阮一峰老师的ES6教程。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/98262.html

相关文章

  • javascript异步Promise.all()、Promise.race()、Promise.

    摘要:的执行与状态无关当得到状态不论成功或失败后就会执行,原文链接参考链接对象 同期异步系列文章推荐谈一谈javascript异步javascript异步中的回调javascript异步与promisejavascript异步之Promise.resolve()、Promise.reject()javascript异步之Promise then和catchjavascript异步之async...

    clasnake 评论0 收藏0
  • javascript异步与promise

    摘要:到这里,我已经发出了一个请求买汉堡,启动了一次交易。但是做汉堡需要时间,我不能马上得到这个汉堡,收银员给我一个收据来代替汉堡。到这里,收据就是一个承诺保证我最后能得到汉堡。 同期异步系列文章推荐谈一谈javascript异步javascript异步中的回调javascript异步之Promise.all()、Promise.race()、Promise.finally()javascr...

    rollback 评论0 收藏0
  • javascript异步函数

    摘要:所以增加了异步函数,提高了代码可读性,对不太熟悉的人而言,帮助就更大了。因为异步函数去掉了所有回调。这就是此代码有效的原因它和以下一样代码更易读正如上面示例所见,与回调和代码相比,异步函数代码看起来非常简单。 这篇文章详细讲解了JavaScript中的异步函数。 JavaScript中的异步代码在很短的时间内从回调发展为Promise,再到ES2017的异步函数,现在我们可以像编写同步...

    WrBug 评论0 收藏0
  • JS笔记

    摘要:从最开始的到封装后的都在试图解决异步编程过程中的问题。为了让编程更美好,我们就需要引入来降低异步编程的复杂性。异步编程入门的全称是前端经典面试题从输入到页面加载发生了什么这是一篇开发的科普类文章,涉及到优化等多个方面。 TypeScript 入门教程 从 JavaScript 程序员的角度总结思考,循序渐进的理解 TypeScript。 网络基础知识之 HTTP 协议 详细介绍 HTT...

    rottengeek 评论0 收藏0
  • Javascript基础-Promise

    摘要:转载自是什么呢根据的定义是一个被用于延时计算的最终结果的占位符这个怎么理解呢比如说,我要去麦当劳买点吃的,下单以后人家会先给你一个订单号,等人家外卖做好了,会提示你,并用那个订单小票来换取你真正的食物,在这时候,那个订单小票就是你这顿饭的 转载自: http://www.lht.ren/article/3/ Promise是什么呢?根据ecma-262的定义: Promise是一个被用...

    Carson 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<