资讯专栏INFORMATION COLUMN

简单实现 ES6 Promise

zhichangterry / 2478人阅读

摘要:实现的一个简单的如果有错误的地方,希望大家能够不吝赐教仅实现及方法最下方有完整代码开始一个对象接收的是一个这个接收两个参数当我们在内执行或的时候,就会调用内定义的和函数然后,和函数会改变的状态所以它应该是像下面这样的保存值记录状态为,为,为

实现的一个简单的ES6 Promise(如果有错误的地方,希望大家能够不吝赐教)
仅实现Promise及.then方法
最下方有完整代码
开始
一个promise对象接收的是一个callback
这个callback接收两个参数(resolve,reject)
当我们在callback内执行resolvereject的时候,就会调用Promise内定义的 resolvereject函数
然后,resolvereject函数会改变Promise的状态
所以它应该是像下面这样的
function MyPromise(callback) {
  // 保存this值
  var self = this
  // 记录状态null为pending,true为resolved,false为reject
  var state = null
  // 记录resolve的参数
  var param = null

  // 执行传入的callback并改变promise对象状态
  callback(resolve, reject)
  // resolve方法
  function resolve(data) {
    // 改变状态
    state = true
    param = data
  }

  // reject方法
  function reject(err) {
    state = false
    param = err
  }
}
但没有then方法的Promise对象是不完整的(完全没有用)
所以我们需要一个then方法,要记住then方法返回的也是一个promise对象
then方法接收两个可选的参数(onFulfilled, onRejected)(我们可以先忽略可选两个字)
then方法传进来的参数必须是函数,如果不是就要忽略(PromiseA+规范)(我们可以也先忽略这句话)
  this.then = function (onFulfilled, onRejected) {
    // 返回一个新的promise对象
    return new self.constructor(function (resolve, reject) {
      // then
    })
  }
接下来就是then方法的具体实现了
then方法中onFulfilled, onRejected的返回值会作为新promise的执行结果

onFulfilled, onRejected这两个函数要在promise的状态变为pending或resolved的时候才能分别执行
所以如果promise方法状态为resolvedrejected的话,我们就可以直接在then方法中执行resolve(onFulfilled(param))reject(onRejected(param))

  this.then = function (onFulfilled, onRejected) {
    // 返回一个新的promise对象
    return new self.constructor(function (resolve, reject) {
       if (state === true) {
        // param是promise对象完成后的结果
        resolve(onFulfilled(param))
      } else if (state === false) {
        reject(onRejected(param))
      } else {
        // 没有执行完毕,怎么办
      }
    })
  }
但如果promise的状态为pending
由于原始promise的状态我们是无法动态获取的,因此我们就需要在他执行状态改变的时候同时执行onFulfilledonRejected方法
我们可以把这个方法放在原始promise对象的resolvereject方法中执行
因此我们要在promise的对象定义中添加四个参数,分别记录onFulfilledonRejected,以及then方法返回的新promise对象的resolvereject
然后如果执行then方法的时候promise对象的状态为pending的话,就将上述四个参数记录起来
// then方法返回的promise对象的resolve和reject
var nextResolve = null
var nextReject = null
// 记录then方法的参数,onFulfilled和onRejected
var asynconFulfilled = null
var asynconRejected = null

//then方法
this.then = function (onFulfilled, onRejected) {
    // 返回一个新的promise对象
    return new self.constructor(function (resolve, reject) {
      if (state === true) {
        // param是promise对象完成后的结果
        resolve(onFulfilled(param))
      } else if (state === false) {
        reject(onRejected(param))
      } else {
        nextResolve = resolve
        nextReject = reject
        asynconFulfilled = onFulfilled
        asynconRejected = onRejected
      }
    })
  }
接下来就是原始promise中的resolvereject的重新实现
 // resolve方法
  function resolve(data) {
    // 改变状态
    state = true
    param = data
    nextResolve(asynconFulfilled(param))
  }

  // reject方法
  function reject(err) {
    state = false
    param = err
    nextReject(asynconRejected(param))
  }
很简单不是吗
我们继续
上述实现我们一直没有考虑一个很重要的情况,如果then方法返回的还是一个promise对象,那么如果我们后边还有then方法的话就要等待前一个then方法中的promise对象的状态从pending变为完成
这要怎么做呢
什么时候可以认为then方法返回的promise对象执行完毕了呢,这里我们就要用到then方法(@_@,边写边用...),
resolve方法为例
var self = this
// resolve方法
function resolve(data) {
  // 记录onFulfilled的执行结果
  let parmise
  // 改变状态
  state = true
  param = data
  // 执行记录的onFulfilled
  parmise = asynconFulfilled(param)
  if(parmise === undefined){
    // 如果parmise为undefined,就不能解析parmise.constructor
  } else if (parmise.constructor === self.constructor) {
    // 等待传递进来的promise对象执行完毕,然后根据传递进来的promise对象的状态执行resolve或reject
    // 注意,这个param是形参,在then方法的promise中执行
    promise.then(function (param) {
      resolve(param)
    }, function (param) {
      reject(param)
    })
  } else {
    // 这个是前边的then返回的不是promise对象的情况
    resolve(promise)
  }
}
前面我们忽略了两点 (then方法接收两个可选的参数(onFulfilled, onRejected)) 和 (then方法传进来的参数必须是函数,如果不是就要忽略)
var self = this
// resolve方法
function resolve(data) {
  // 记录onFulfilled的执行结果
  var parmise
  // 改变状态
  state = true
  param = data
  // 执行记录的onFulfilled
  // begin--------------
  if (typeof onFulfilled === "function") {
    promise = onFulfilled(param)
    if (promise === undefined) {
      // 待补充
    } else if (promise.constructor === self.constructor) {
      // 注意,这个param是形参,在then方法的promise中执行
      promise.then(function (param) {
        resolve(param)
      }, function (param) {
        reject(param)
      })
    } else {
      reject(promise)
    }
  } else {
    // 如果onFulfilled不是function,忽略,直接resolve或reject
    resolve(param)
  }
  // ---------------end
}
上面begin到end之间的代码还要在then方法调用,所以我们可以把这段代码抽象为一个函数
resolve reject的原理相同,只要注意如果不是function 的话需要执行reject
onFulfilled和 onRejected只有在[执行环境]堆栈仅包含平台代码时才可被调用
所以将上述begin-end之间的代码放到seTimeout中执行(浏览器环境)
function resolve(data) {
  // 记录onFulfilled的执行结果
  var parmise
  // 改变状态
  state = true
  param = data
  // 执行记录的onFulfilled
  window.setTimeout(function () {
    // begin--------------
    // 上述代码
    // ---------------end
  }, 0)
}
下面是完整代码
注:没有实现正确的事件循环
// 简单实现ES6 Promise
function MyPromise(callback) {
  // 保存this值
  var self = this
  // 记录状态null为pending,true为resolved,false为reject
  var state = null
  // 记录resolve的参数
  var param = null
  // then方法返回的promise对象的resolve和reject
  var nextResolve = null
  var nextReject = null
  // 记录then方法的参数,onFulfilled和onRejected
  var asynconFulfilled = null
  var asynconRejected = null

  // 执行并改变promise对象状态
  callback(resolve, reject)
  // then方法
  this.then = function (onFulfilled, onRejected) {
    // 返回一个新的promise对象
    return new self.constructor(function (resolve, reject) {
      // 判断异步代码是否执行完毕(是否resolve或reject)
      // 若执行完毕就在then方法中立即执行,否则将四个参数记录下来,等待state就绪后再执行doAsyn*函数
      if (state === true) {
        doAsynconFulfilled(onFulfilled, resolve, reject)
      } else if (state === false) {
        doAsynconRejected(onRejected, resolve, reject)
      } else {
        nextResolve = resolve
        nextReject = reject
        asynconFulfilled = onFulfilled
        asynconRejected = onRejected
      }
    })
  }
  // resolve方法
  function resolve(data) {
    // 改变状态
    state = true
    param = data
    if(nextResolve){
        doAsynconFulfilled(asynconFulfilled, nextResolve, nextReject)
    }
  }

  // reject方法
  function reject(err) {
    state = false
    param = err
    if(nextReject){
        doAsynconRejected(asynconRejected, nextResolve, nextReject)
    }
  }

  // 核心方法(我觉得是)

  function doAsynconFulfilled(onFulfilled, resolve, reject) {
      window.setTimeout(function () {
        // 判断onFulfilled是否为function,不是则忽略
        if (typeof onFulfilled === "function") {
          // 执行onFulfilled方法获取返回值promise()
          let promise = onFulfilled(param)
          // 如果promise为undefined 执行 if
          // 如果promise为MyPromise对象 执行 else if
          // 如果promise为非MyPromise对象 执行 else
          if (promise === undefined) {
            resolve(param)
            // 待补充
          } else if (promise.constructor === self.constructor) {
            // 等待传递进来的promise对象执行完毕,然后根据传递进来的promise对象的状态执行resolve或reject
            promise.then(function (param) {
              resolve(param)
            }, function (param) {
              reject(param)
            })
          } else {
            // 执行then方法返回的对象的resolve
            resolve(promise)
          }
        } else {
          // 传递参数
          resolve(param)
        }
      }, 0)
    
  }

  function doAsynconRejected(onRejected, resolve, reject) {
    window.setTimeout(function () {
        if (typeof onRejected === "function") {
          let promise = onRejected(param)
          if (promise === undefined) {
            reject(param)
            // 待补充
          } else if (promise.constructor === self.constructor) {
            promise.then(function (param) {
              resolve(param)
            }, function (param) {
              reject(param)
            })
          } else {
            reject(promise)
          }
        } else {
          // 传递错误信息
          reject(param)
        }
    }, 0)
  }
}
// 测试使用
var b = function (message) {
    return new MyPromise(function (resolve, reject) {
        document.body.onclick = function () {
            resolve("click:" + message)
        }
    })
}
var a = new MyPromise(function (resolve, reject) {
  resolve(123)
}).then(function (message) {
    return b(message)
}).then().then(function (message) {
    console.log("final:" + message)
},function (err) {
    console.log("final:" + err)
})
console.log("window")
当然还有Promise.all等方法。
完毕!

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

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

相关文章

  • ES6-7

    摘要:的翻译文档由的维护很多人说,阮老师已经有一本关于的书了入门,觉得看看这本书就足够了。前端的异步解决方案之和异步编程模式在前端开发过程中,显得越来越重要。为了让编程更美好,我们就需要引入来降低异步编程的复杂性。 JavaScript Promise 迷你书(中文版) 超详细介绍promise的gitbook,看完再不会promise...... 本书的目的是以目前还在制定中的ECMASc...

    mudiyouyou 评论0 收藏0
  • JavaScript 异步

    摘要:从最开始的到封装后的都在试图解决异步编程过程中的问题。为了让编程更美好,我们就需要引入来降低异步编程的复杂性。写一个符合规范并可配合使用的写一个符合规范并可配合使用的理解的工作原理采用回调函数来处理异步编程。 JavaScript怎么使用循环代替(异步)递归 问题描述 在开发过程中,遇到一个需求:在系统初始化时通过http获取一个第三方服务器端的列表,第三方服务器提供了一个接口,可通过...

    tuniutech 评论0 收藏0
  • 谈谈ES6前后的异步编程

    摘要:回调函数这是异步编程最基本的方法。对象对象是工作组提出的一种规范,目的是为异步编程提供统一接口。诞生后,出现了函数,它将异步编程带入了一个全新的阶段。 更多详情点击http://blog.zhangbing.club/Ja... Javascript 语言的执行环境是单线程的,如果没有异步编程,根本没法用,非卡死不可。 为了解决这个问题,Javascript语言将任务的执行模式分成两种...

    fizz 评论0 收藏0
  • 通过 ES6 Promise 和 jQuery Deferred 的异同学习 Promise

    摘要:和和都有和,但是略有不同。实际上返回的是一个对象。和添加的回调,添加的回调。所以在调用成功的情况下执行添加的回调,调用失败时执行添加的回调。,产生对象并,产生对象并,然后继续处理,的语法糖,和的差不多但不同。 Deferred 和 Promise ES6 和 jQuery 都有 Deffered 和 Promise,但是略有不同。不过它们的作用可以简单的用两句话来描述 Deffere...

    Yujiaao 评论0 收藏0
  • 一篇文章用ES6手撸一个Promise

    摘要:本篇文章将会尝试用简单易懂的语言描述的原理,并且用手撸一个简单的。一个后可以通过方法,指定和时的回调函数。实现实现状态机因为是一个构造函数,使用的写法,首先想到的就是有显式声明的。 说到Promise,都知道它是比回调函数更优的一种异步编程解决方案,它可以使得异步操作逻辑变得更加清晰,是解决地狱回调的一种尝试。本篇文章将会尝试用简单易懂的语言描述Promise的原理,并且用es6手撸一...

    hsluoyz 评论0 收藏0

发表评论

0条评论

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