Promise的简单实现

数字舵手
• 阅读 1016

Promise本意是承诺.主要目的是为了解决在需要多个异步操作的时候.产生的回调嵌套.在es6没出来前.用bluebird来实现.与javas中的Q模块类似.

Promise对象实例创建的过程中有三种状态, Pending、Fulfilled、Rejected. Fulfilled与Rejected间不能相互转换

Promise的简单实现

promise的使用与原理实现

then

promise.then用于链式调用,每次执行时都会返回一个新的promise对象

all

接收一个promise数组,如果状态都为resolve则返回Promise的resolve状态,如果某个promise状态为reject则返回Promise的reject状态

race

接收一个promise数组, 比谁跑的快.返回第一完成的Promise状态

promise功能的简单实现

const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'
function Promise(executor) {
  let self = this
  // 初始化
  self.status = PENDING
  // 定义回调
  self.onResolvedCallbacks = []
  self.onRejectedCallbacks = []

  function resolve(value) {
    if (value != null && value.then && typeof value.then === 'function') {
      return value.then(resolve, reject)
    }
    // 如果是初始状态.则改变成成功状态
    setTimeout(() => {
      if (self.status === PENDING) {
        self.status = FULFILLED
        self.value = value
        // 调用所有的成功
        self.onResolvedCallbacks.forEach(cb => cb(self.value))
      }
    })
  }

  function reject(reason) {
    setTimeout(() => {
      if (self.status === PENDING) {
        self.status = REJECTED
        self.value = reason
        self.onRejectedCallbacks.forEach(cb => cb(self.value))
      }
    })
  }
  try {
    // 捕获函数执行时出现的异常
    executor(resolve, reject)
  } catch(e) {
    reject(e)
  }
}

function resolvePromise(promise2, x, resolve, reject) {
  if (promise2 === x) {
    return reject(new TypeError('循环引用'))
  }
  let called = false
  if (x instanceof Promise) {
    if (x.status === PENDING) {
      x.then(function(y){
        resolvePromise(promise2, y, resolve, reject)
      }, reject)
    } else {
      x.then(resolve, reject)
    }
  } else if(x != null && ((typeof x === 'object') || (typeof x.then === 'function'))) {
    // 兼容性处理
    consoole.log('兼容性处理')
    try {
      let then = x.then
      if (typeof then === 'function') {
        then.call(x, (y) => {
          if (called) return
          called = true
          resolvePromise(promise2, y, resolve, reject)
        }, (err) => {
          if (called) return
          called = true
          reject(err)
        })
      } else {
        resolve(x)
      }
    } catch(e) {
      if (called) return
      called = true
      reject(e)
    }
  } else {
    // x是一个普通的值
    resolve(x)
  }
}

Promise.prototype.then = function(onFulfilled, onRejected) {
  onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : function(value) {return value}
  onRejected = typeof onRejected === 'function' ? onRejected : function(reason) {throw reason}
  let self = this
  let promise2
  if (self.status == FULFILLED) {
    return  promise2 = new Promise((resolve, reject) => {
      setTimeout(() => {
        try {
          let x = onFulfilled(self.value);
          //如果获取到了返回值x,会走解析Promise的过程
          resolvePromise(promise2, x, resolve, reject);
        } catch(e) {
          //如果执行成功的回调过程中出错了,用错误原因把Promise2 reject
          reject(e);
        }
      })
    })
  }
  if (self.status == REJECTED) {
    return  promise2 = new Promise((resolve, reject) => {
      setTimeout(() => {
        try {
          let x = onRejected(self.value);
          resolvePromise(promise2, x, resolve, reject);
        } catch(e) {
          reject(e);
        }
      })
    })
  }
  if(self.status == PENDING){
    return promise2 = new Promise(function(resolve,reject){
      self.onResolvedCallbacks.push(function(){
          try{
            let x =onFulfilled(self.value);
            //如果获取到了返回值x,会走解析promise的过程
            resolvePromise(promise2,x,resolve,reject);
          }catch(e){
            reject(e);
          }
 
      });
      self.onRejectedCallbacks.push(function(){
          try{
            let x =onRejected(self.value);
            resolvePromise(promise2,x,resolve,reject);
          }catch(e){
            reject(e);
          }
      });
    });
   }
}

Promise.prototype.catch = function(onRejected) {
  this.then(null, onRejected)
}

Promise.race = function(promises) {
  return new Promise((resolve, reject) => {
    for (let i = 0; i < promises.length; i++) {
      promises[i].then(resolve, reject)
    }
  })
}

Promise.deferred = Promise.defer = function(){
  let defer = {};
  defer.promise = new Promise((resolve,reject) => {
    defer.resolve = resolve;
    defer.reject = reject;
  });
  return defer;
}
Promise.resolve = function (value) {
  return new Promise((resolve, reject) => resolve(value))
}
Promise.reject = function (reason) {
  return new Promise((resolve, reject) => reject(reason))
}

Promise.all = function (promises) {
  return new Promise((resolve, reject) => {
    let done = gen(promises.length, resolve)
    for (let i = 0; i < promises.length; i++) {
      promises[i].then(val => {
        done(i, val)
      }, reject)
    }
  })
}

function gen(i, val) {
  let count = 0, result = []
  return function (i, val) {
    result[i] = val
    if (++count === i) {
      resolve(result)
    }
  }
}

module.exports = Promise
点赞
收藏
评论区
推荐文章
Chase620 Chase620
4年前
Promise从入门到拿Offer之手写Promise
1、Promise构造函数的实现Promise构造函数用来声明示例对象,需要传入一个执行器函数。其中包括resolve函数和reject函数,以及几个重要的属性:状态属性、结果属性和回调函数队列。构造函数的基本框架resolve函数用于异步处理成功后调用的函数。其中包括验证对象状态修改次数,修改promise实例对象状态,异步调用成功的回调函数
Stella981 Stella981
3年前
JavaScript中Promise 使用、原理以及实现过程
1.什么是Promisepromise是目前JS异步编程的主流解决方案,遵循Promises/A方案。2.Promise原理简析(1)promise本身相当于一个状态机,拥有三种状态pendingfulfilledrejected一个promise对象初始化时
Stella981 Stella981
3年前
Promise的奇怪用法和自己实现一个Promise
原文链接: Promise的奇怪用法和自己实现一个Promise(https://my.oschina.net/ahaoboy/blog/4645165)使用Promise实现一个页面所有图片加载完毕的回调importReact,{useEffect}from"react";exportdefault()
Stella981 Stella981
3年前
Javascript 中的神器——Promise
_摘要:_ 回调函数真正的问题在于他剥夺了我们使用return和throw这些关键字的能力。而Promise很好地解决了这一切回调函数真正的问题在于他剥夺了我们使用return和throw这些关键字的能力。而Promise很好地解决了这一切Promise概念所谓Promise,就是ES6原生提供的一个
Stella981 Stella981
3年前
ES6中的Promise和Generator详解
简介ES6中除了上篇文章讲过的语法新特性和一些新的API之外,还有两个非常重要的新特性就是Promise和Generator,今天我们将会详细讲解一下这两个新特性。Promise什么是PromisePromise是异步编程的一种解决方案,比传统的解决方案“回调函数和事件”更合理和更强大。所谓P
Stella981 Stella981
3年前
ES6中自带的promise的问题
ES6中的Promise作用:解决异步嵌套问题。但是只能解决两层嵌套,不能解决两层以上嵌套;解决方法是我自己封装的函数如下:functionPromising(){var_arr;this.thenfunction(fx){
Stella981 Stella981
3年前
JavaScript回调函数的高手指南
摘要:本文将会解释回调函数的概念,同时帮你区分两种回调:同步和异步。回调函数是每个前端程序员都应该知道的概念之一。回调可用于数组、计时器函数、promise、事件处理中。本文将会解释回调函数的概念,同时帮你区分两种回调:同步和异步。1.回调函数首先写一个向人打招呼的函数。只需要创建一个接受name参数的函数gree
Stella981 Stella981
3年前
ES6 Promise 对象扯谈
newPromise(/executor/function(resolve,reject){...});Promise的构造函数接收一个函数作为参数,函数里面传入两个参数:resolve,reject,分别表示异步操作执行成功后的回调函数和异步操作执行失败后的回调函数。其实这里用“成功”和“失败”来描述并不准确,按照标准来
Stella981 Stella981
3年前
Promise 多重链式调用
Promise对象是用于异步操作的。Promise的真正强大之处在于它的多重链式调用,可以避免层层嵌套回调。如果我们在第一次ajax请求后,还要用它返回的结果再次请求呢?使用Promise,我们就可以利用then进行「链式回调」,将异步操作以同步操作的流程表示出来。以下是个小Demo:/e.g/sen
Promise规范与原理解析 | 京东物流技术团队
Promise对象用于清晰的处理异步任务的完成,返回最终的结果值,本次分享主要介绍Promise的基本属性以及Promise内部的基础实现,能够帮我们更明确使用场景、更快速定位问题。
京东云开发者 京东云开发者
8个月前
Promise规范与原理解析
作者:京东物流孙琦摘要Promise对象用于清晰的处理异步任务的完成,返回最终的结果值,本次分享主要介绍Promise的基本属性以及Promise内部的基础实现,能够帮我们更明确使用场景、更快速定位问题。Promise出现的原因首先我们先来看一段代码:异步