美文网首页
Promise基本概念

Promise基本概念

作者: 书生逛酒家 | 来源:发表于2021-06-29 17:33 被阅读0次

Promise用的很多,比较熟悉Promise的使用,一直没有思考过Promise的实现,今天尝试着写一个完整的Promise。

第一部分 - 简单的Promise实现

function Promise(fn) {
// 存放onFulfilled队列
  let callback = [];
  fn(reslove);

  function reslove(value) {
      callback.forEach(fn => fn(value))
  }

  this.then = function (fn) {
    callback.push(fn)
  };
}

let p = new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve('hello')
    }, 100);
})

p.then(res => {
    console.log(res)
})
// hello
  • 创建Promise的实例传入一个函数,将resolve作为函数参数,异步执行后的结果作为resolve的参数。then函数在异步执行前已经执行。

第二部分 - Promise链式调用

  • 在then函数里添加一个return Promise实例
function Promise(fn) {
  let callback = [];
  fn(reslove);

  function reslove(value) {
      callback.forEach(fn => fn(value))
  }
// 在then函数加一个return就可以了
  this.then = function (fn) {
    callback.push(fn)
    return this
  };
}

let p = new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve('hello')
    }, 100);
})

p.then(res => {
    console.log(res)
}).then(res => {
    console.log(res)
}).then(res => {
    console.log(res)
})
// hello hello hello
  • 保证链式调用返回的是相同的value,如果不同的需要做不同的处理

第三部分 - 同步异步

  • 创建Promise的实例传入的函数内部是一个异步函数,如果是同步函数导致then函数不执行,因为callback是一个空数组,onfulfilled函数还没有注册。
  • 为了解决同步异步问题,增加一个状态管理
    • 待定(pending): 初始状态,既没有被兑现,也没有被拒绝。
    • 已兑现(fulfilled): 意味着操作成功完成。
    • 已拒绝(rejected): 意味着操作失败。
const PENDING = 0
const FULFILLED = 1
const REJECTED = 2

function Promise(fn) {
  this.handlers = [];
  this.state = PENDING
  this.value = null
  fn(reslove.bind(this));

  function reslove(value) {
    this.state = FULFILLED
    this.value = value
    this.handlers.forEach(fn => fn(value))
  }

  this.then = function (onfulfilled) {
    if (this.state === PENDING) {
        this.handlers.push(onfulfilled)
    } else {
        onfulfilled(this.value)
    }
    return this
  };
}

let p = new Promise((resolve, reject) => {
    resolve('hello')
})

p.then(res => {
    console.log(res)
})
  • 如果是同步执行直接,直接把value值给到传入到then的函数。反之,handlers队列不为空。

第四部分 - 真正的Promise链式调用

  • 第二部分的链式调用在层层递进的过程中返回都是相同的value,如果每个then返回不同的Promise,这就不是我们希望看到的效果。真正的链式调用应该是返回一个新的Promise实例,这里我们可以通过then函数返回一个新的Promise实例。
const PENDING = 0
const FULFILLED = 1
const REJECTED = 2

function Promise(fn) {
  this.handlers = [];
  this.state = PENDING
  this.value = null
  fn(reslove.bind(this));

  function reslove(value) {
    // 如果接受到的value是一个Promise实例,未作处理
    this.state = FULFILLED
    this.value = value
    // 执行handlers队列函数
    this.handlers.forEach(fn => this.handle(fn))
  }

  this.handle = (fn) => {
    // 在resolve之前添加到handlers队列
    if (this.state === PENDING) {
      this.handlers.push(fn)
      return
    }
    // then函数没有传递任何参数
    //这个部分意义不大,但是要做处理,很少有then为空的情况
    if (!fn.onfulfilled) {
      fn.resolve(this.value)
      return
    }
    // 真正的链式调用返回的ret是一个Promise实例
    // 同步和异步执行直接把value给到then传入函数
    let ret = fn.onfulfilled(this.value);
    // 这里把返回的Promise实例给到resolve函数
    fn.resolve(ret)
  }

  this.then = function (onfulfilled) {
    // 链式调用,返回一个新的Promise实例
    return new Promise((resolve, reject) => {
      this.handle({
        onfulfilled,
        resolve
      })
    })
  };
}

let p = () => {
  return new Promise((resolve, reject) => {
    resolve('hello')
  })
}

p().then(res => {
  console.log(res)
})
// hello
  • 上图的then函数返回一个Promise的实例,then和resolve共用一个handle函数。但是如果多个then函数返回Promise实例还是不支持。这里需要在resolve做个处理。
    在resolve中处理传入的Promise实例的参数
const PENDING = 0
const FULFILLED = 1
const REJECTED = 2

function Promise(fn) {
  this.handlers = [];
  this.state = PENDING
  this.value = null
  fn(resolve.bind(this));

  function resolve(value) {
    // 如果接受到的value是一个Promise实例
    const nameList = ['object', 'function']
    if (value && nameList.includes(typeof value)) {
      const then = value.then
      if (nameList.includes(typeof then)) {
        then.call(value, resolve.bind(this))
        return
      }
    }
    this.state = FULFILLED
    this.value = value
    // 执行handlers队列函数
    this.handlers.forEach(fn => this.handle(fn))
  }

  this.handle = (fn) => {
    // 在resolve之前添加到handlers队列
    if (this.state === PENDING) {
      this.handlers.push(fn)
      return
    }
    // then函数没有传递任何参数
    if (!fn.onfulfilled) {
      fn.resolve(this.value)
      return
    }
    // 真正的链式调用返回的ret是一个Promise实例
    // 同步和异步执行直接把value给到then传入函数
    let ret = fn.onfulfilled(this.value);
    // 这里把返回的Promise实例给到resolve函数
    fn.resolve(ret)
  }

  this.then = function (onfulfilled) {
    // 链式调用,返回一个新的Promise实例
    return new Promise((resolve, reject) => {
      this.handle({
        onfulfilled,
        resolve
      })
    })
  };
}

let p = () => {
  return new Promise((resolve, reject) => {
    resolve('hello')
  })
}

let p1 = () => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve('hello1')
    }, 100);
  })
}

let p2 = () => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve('hello2')
    }, 100);
  })
}

let p3 = () => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve('hello3')
    }, 100);
  })
}

p().then(res => {
  console.log(res)
  return p1()
}).then(res => {
  console.log(res);
  return p2()
}).then(res => {
  console.log(res);
  return p3()
}).then(res => {
  console.log(res);
})
  • Promise的实现链式调用,也就是纵向发展,使得callback hell现象不复存在。

相关文章

  • Vue-promise请求数据&调用方法

    1. Promise 基本概念: Promise是一个构造函数,所以可以 new 出一个Promise的实例; 在...

  • 手写一个符合Promise/A+规范的Promise

    Promise的基本概念: Promise使异步脱离了回调地狱,可以更优雅的操作异步函数的执行结果。究其根本,不过...

  • Promise基本概念

    Promise用的很多,比较熟悉Promise的使用,一直没有思考过Promise的实现,今天尝试着写一个完整的P...

  • promise经典面试题

    上期讲了promise基本概念和用法,今天结合上期的内容,讲解几道经典的相关面试题。 promise基本规则: 1...

  • es6解读5:promise

    Promise作为ES6中最重要的特性之一,我们有必要掌握并理解透彻。本文将由浅到深,讲解Promise的基本概念...

  • 解析Promise

    Promise作为ES6中最重要的特性之一,我们有必要掌握并理解透彻。本文将由浅到深,讲解Promise的基本概念...

  • es6解读5-promise

    Promise作为ES6中最重要的特性之一,我们有必要掌握并理解透彻。本文将由浅到深,讲解Promise的基本概念...

  • 异步操作 Promise

    基本概念:Promise:是ES6中新增的异步编程解决方案,体现在代码中它是一个对象,可以通过 Promise 构...

  • JS笔记-promise

    基本概念比灵活的运用更加重要。理解了基本概念,才不会在数量巨大的名词前迷失。 Javascript的promise...

  • ES6 - Promise

    基本概念 Promise 对象有三种状态:pending,resolved,rejected只有异步操作的结果,可...

网友评论

      本文标题:Promise基本概念

      本文链接:https://www.haomeiwen.com/subject/tyeazhtx.html