验证码: 看不清楚,换一张 查询 注册会员,免验证
  • {{ basic.site_slogan }}
  • 打开微信扫一扫,
    您还可以在这里找到我们哟

    关注我们

JS中Promise的使用及封装方法是什么

阅读:466 来源:乙速云 作者:代码code

JS中Promise的使用及封装方法是什么

      Promise 是什么

      • Promise 是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大。

      • 简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。

      • 从语法上说,Promise 是一个对象,从它可以获取异步操作的消息。Promise 提供统一的 API,各种异步操作都可以用同样的方法进行处理。

      Promise 的特点

      1. 对象的状态不受外界影响。Promise 对象代表一个异步操作,有三种状态:pending(进行中)、fulfilled(已成功)和 rejected(已失败)。只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。这也是 Promise 这个名字的由来,它的英语意思就是“承诺”,表示其他手段无法改变

      2. 一旦状态改变,就不会再变,任何时候都可以得到这个结果。Promise 对象的状态改变,只有两种可能:从 pending 变为 fulfilled 和从 pending 变为 rejected。只要这两种情况发生,状态就凝固了,不会再变了,会一直保持这个结果,这时就称为 resolved(已定型)。如果改变已经发生了,你再对 Promise 对象添加回调函数,也会立即得到这个结果。这与事件(Event)完全不同,事件的特点是,如果你错过了它,再去监听,是得不到结果的。

      3. 将异步操作以同步操作的流程表达出来,避免了层层嵌套的回调函数(回调地狱)

      Promise 的缺点

      • 1. 无法取消 Promise,一旦新建它就会立即执行,无法中途取消

      • 2. 如果不设置回调函数,Promise内部抛出的错误,不会反应到外部

      • 3. 当处于pending状态时,无法得知目前进展到哪一个阶段(刚刚开始还是即将完成)

      Promise 的原理

      ES6 规定,Promise 对象是一个构造函数,用来生成 Promise 实例。通过在函数内部 return 一个 Promise 对象的实例,这样就可以使用 Promise 的属性和方法进行下一步操作了。    

      Promise 构造函数接受一个函数作为参数,该函数的两个参数分别是 resolve 和 reject。它们是两个函数,由 JavaScript 引擎提供,不用自己部署

      const promise = new Promise(function(resolve, reject) {
        if (/* 异步操作成功 */){
          resolve(value)
        } else {
          reject(error)
        }
      })

      Promise 的方法

      1. Promise.prototype.then()

      then()方法就是把原来的回调写法分离出来,在异步操作执行完后,用链式调用的方式执行回调函数。

      而 Promise的优势就在于这个链式调用。

      我们可以在 then 方法中继续写 Promise 对象并返回,然后继续调用 then 来进行回调操作。

      resolve 的用法

      let promise = new Promise(function(resolve, reject) {
        console.log('Promise')
        resolve('已完成')
      });
      
      promise.then(function(data) {
        console.log('resolved.',data)
      })
      
      console.log('Hi!')
      
      //  Promise
      //  Hi!
      //  resolved. 123

      reject 的用法

      reject 方法就是把 Promise 的状态置为已失败(Rejected),这时 then 方法执行“失败”情况的回调(then 方法的第二参数)

      let promise = new Promise(function(resolve, reject) {
        reject('NO')
      });
      
      promise.then(function(data) {
        console.log('resolved.',data)
      },function(data){
        console.log('rejected.',data)
      })
      
      //  rejected. NO

      2. Promise.prototype.catch()

      如果异步操作抛出错误,当前 Promise 对象状态就会变为 rejected,就会调用 catch 方法指定的回调函数,处理这个错误。

      另外,then 方法指定的回调函数,如果运行中抛出错误,也会被 catch 方法捕获。

      catch 方法返回的也是一个 Promise 对象,因此后面还可以接着调用then方法。

      const promise = new Promise(function(resolve, reject) {
        resolve('OK')
      })
      
      promise.then(function(data) {
        console.log(data)
        console.log(num)
      }).catch(function(err) {
        console.log(err)
      })
      
      // OK
      // ReferenceError: num is not defined

      3. Promise.prototype.finally()

      finally 方法用于指定不管 Promise 对象最后状态如何,在执行完 then 或 catch 指定的回调函数以后,都会执行 finally 方法指定的回调函数。

      finally 方法的回调函数不接受任何参数,在 finally 方法里面的操作,与状态无关,不依赖于 Promise 的执行结果。

      // 服务器使用 Promise 处理请求,然后使用 finally 方法关掉服务器
      server.listen(port)
        .then(function () {
          // ...
        })
        .finally(server.stop)

      4. Promise.all()

      Promise 的 all 方法(传入一个数组,每一项分别是一个 Promise 实例)提供了并行执行异步操作的能力,并且在所有异步操作执行完(所有实例的状态都变成 fulfilled)或者 只要有一个 Promise 实例的状态变为 reject,Promise.all 的状态就会变为 reject,然后执行回调。可以将数组里的 Promise 看成是 “与” 关系。

      应用场景:打开网页时,预先加载需要用到的各种资源如图片、flash 以及各种静态文件。所有的都加载完后,我们再进行页面的初始化

      //买作业本
      function cutUp() {
        console.log('挑作业本')
        var p = new Promise(function(resolve, reject) { //做一些异步操作
          console.log('挑好购买作业本')
            resolve('新的作业本')
        })
        return p
      }
              
      //买笔
      function boil() {
        console.log('挑笔芯')
        var p = new Promise(function(resolve, reject) { //做一些异步操作
          console.log('挑好购买笔芯')
          resolve('新的笔芯')
        });
        return p
      }
      
      Promise.all([cutUp(),boil()]).then(function(res) {
        console.log("写作业的工具都买好了")
        console.log(res)
      })
      
      // 挑作业本
      // 挑好购买作业本
      // 挑笔芯
      // 挑好购买笔芯
      // 写作业的工具都买好了
      // ["新的作业本", "新的笔芯"]

      5. Promise.race()

      Promise.race 方法( 传入一个数组,每一项分别是 Promise 实例 )的用法与 all 一样,异步操作同样是并行执行的。只不过 all 是等所有异步操作都执行完毕后才执行 then 回调。race 可以看到 是 “或” 关系,只要有一个异步操作执行完毕,就会立刻执行 then 回调。

      应用场景:用 race 给某个异步请求设置超时时间,并且在超时后执行相应的操作

      //买作业本
      function cutUp() {
        console.log('挑作业本')
        var p = new Promise(function(resolve, reject) { //做一些异步操作
          console.log('挑好购买作业本')
            resolve('新的作业本')
        })
        return p
      }
              
      //买笔
      function boil() {
        console.log('挑笔芯')
        var p = new Promise(function(resolve, reject){ //做一些异步操作
          console.log('挑好购买笔芯')
          resolve('新的笔芯')
        })
        return p
      }
      
      Promise.race([cutUp(),boil()]).then(function(res){
        console.log("写作业的工具都买好了")
        console.log(res)
      })
      
      // 挑作业本
      // 挑好购买作业本
      // 挑笔芯
      // 挑好购买笔芯
      // 写作业的工具都买好了
      // 新的作业本

      5. Promise.allSettled()

      Promise.allSettled() 方法接受一组 Promise 实例作为参数,包装成一个新的 Promise 实例 。

      只有等到所有这些参数实例都返回结果,不管是 fulfilled 还是 rejected,包装实例才会结束。

      Promise.allSettled()的返回值该是一个数组,数组里每个对象都有 status 属性,该属性的值只可能是字符串 fulfilled 或字符串rejected。

      fulfilled 时,对象有 value 属性,rejected 时有 reason 属性,对应两种状态的返回值。

      应用场景:不关心异步操作的结果,只确保所有异步操作都结束

      //买作业本
      function cutUp() {
        console.log('挑作业本')
        var p = new Promise(function(resolve, reject) { //做一些异步操作
          console.log('挑好购买作业本')
            resolve('新的作业本')
        })
        return p
      }
              
      //买笔
      function boil() {
        console.log('挑笔芯')
        var p = new Promise(function(resolve, reject){ //做一些异步操作
          console.log('挑好购买笔芯')
          reject('购买不了,没钱了')
        })
        return p
      }
      
      Promise.allSettled([cutUp(),boil()]).then(function(res){
        console.log("写作业的工具没有买齐")
        console.log(res)
      })
      
      // 挑作业本
      // 挑好购买作业本
      // 挑笔芯
      // 挑好购买笔芯
      // 写作业的工具没有买齐
      // [
      //   {status: "fulfilled", value: "新的作业本"}
      //   {status: "rejected", reason: "购买不了,没钱了"}
      // ]

      Promise 的简单封装

      function promiseM(callback) {
          this.status = 'pendding'
          this.msg = ''
      
          callback((data) => {
              this.status = 'resolve'
              this.msg = data
          },(err) => {
          if (this.status === 'resolve') return
              this.status = 'reject'
              this.msg = err
          })
      }
      
      promiseM.prototype.then = function () {
          let cb = arguments
          let that = this
          let timer = setInterval(function () {
              if(that.status == 'resolve') {
                  cb[0](that.msg)
                  clearInterval(timer)
              } else if(that.status == 'reject') {
                  if(!cb[1]) {
                      clearInterval(timer)
                      throw that.msg + ' No Exit'
                  } else {
                      cb[1](that.msg)
                      clearInterval(timer)
                  }
              }
          }, 500)
      }
      
      function fn() {
          return new promiseM(function (resolve, reject) {
              resolve('success')
          })
      }
      
      fn().then(function (res) {
          console.log(res)
      })
      
      // success
    分享到:
    *特别声明:以上内容来自于网络收集,著作权属原作者所有,如有侵权,请联系我们: hlamps#outlook.com (#换成@)。
    相关文章
    {{ v.title }}
    {{ v.description||(cleanHtml(v.content)).substr(0,100)+'···' }}
    你可能感兴趣
    推荐阅读 更多>