iis服务器助手广告广告
返回顶部
首页 > 资讯 > 精选 >JavaScript怎么实现手写promise
  • 391
分享到

JavaScript怎么实现手写promise

2023-07-06 01:07:24 391人浏览 八月长安
摘要

这篇文章主要介绍了javascript怎么实现手写promise的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇JavaScript怎么实现手写promise文章都会有所收获,下面我们一起来看看吧。需求我们先来总

这篇文章主要介绍了javascript怎么实现手写promise的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇JavaScript怎么实现手写promise文章都会有所收获,下面我们一起来看看吧。

需求

我们先来总结一下 promise 的特性:

使用:

const p1 = new Promise((resolve, reject) => {  console.log('1');  resolve('成功了');})console.log("2");const p2 = p1.then(data => {  console.log('3')  throw new Error('失败了')})const p3 = p2.then(data => {  console.log('success', data)}, err => {  console.log('4', err)})

JavaScript怎么实现手写promise

JavaScript怎么实现手写promise

以上的示例可以看出 promise 的一些特点,也就是我们本次要做的事情:

  • 在调用 Promise 时,会返回一个 Promise 对象,包含了一些熟悉和方法(all/resolve/reject/then…)

  • 构建 Promise 对象时,需要传入一个 executor 函数,接受两个参数,分别是resolve和reject,Promise 的主要业务流程都在 executor 函数中执行。

  • 如果运行在 excutor 函数中的业务执行成功了,会调用 resolve 函数;如果执行失败了,则调用 reject 函数。

  • promise 有三个状态:pending,fulfilled,rejected,默认是 pending。只能从pending到rejected, 或者从pending到fulfilled,状态一旦确认,就不会再改变;

  • promise 有一个then方法,接收两个参数,分别是成功的回调 onFulfilled, 和失败的回调 onRejected。

// 三个状态:PENDING、FULFILLED、REJECTEDconst PENDING = "PENDING";const FULFILLED = "FULFILLED";const REJECTED = "REJECTED";class Promise {  constructor(executor) {    // 默认状态为 PENDING    this.status = PENDING;    // 存放成功状态的值,默认为 undefined    this.value = undefined;    // 存放失败状态的值,默认为 undefined    this.reason = undefined;    // 调用此方法就是成功    let resolve = (value) => {      // 状态为 PENDING 时才可以更新状态,防止 executor 中调用了两次 resovle/reject 方法      if (this.status === PENDING) {        this.status = FULFILLED;        this.value = value;      }    };    // 调用此方法就是失败    let reject = (reason) => {      // 状态为 PENDING 时才可以更新状态,防止 executor 中调用了两次 resovle/reject 方法      if (this.status === PENDING) {        this.status = REJECTED;        this.reason = reason;      }    };    try {      // 立即执行,将 resolve 和 reject 函数传给使用者      executor(resolve, reject);    } catch (error) {      // 发生异常时执行失败逻辑      reject(error);    }  }  // 包含一个 then 方法,并接收两个参数 onFulfilled、onRejected  then(onFulfilled, onRejected) {    if (this.status === FULFILLED) {      onFulfilled(this.value);    }    if (this.status === REJECTED) {      onRejected(this.reason);    }  }}

调用一下:

const promise = new Promise((resolve, reject) => {  resolve('成功');}).then(  (data) => {    console.log('success', data)  },  (err) => {    console.log('faild', err)  })

JavaScript怎么实现手写promise

这个时候我们很开心,但是别开心的太早,promise 是为了处理异步任务的,我们来试试异步任务好不好使:

const promise = new Promise((resolve, reject) => {  // 传入一个异步操作  setTimeout(() => {    resolve('成功');  },1000);}).then(  (data) => {    console.log('success', data)  },  (err) => {    console.log('faild', err)  })

发现没有任何输出,我们来分析一下为什么:

new Promise 执行的时候,这时候异步任务开始了,接下来直接执行 .then 函数,then函数里的状态目前还是 padding,所以就什么也没执行。

那么我们想想应该怎么改呢?

我们想要做的就是,当异步函数执行完后,也就是触发 resolve 的时候,再去触发 .then 函数执行并把 resolve 的参数传给 then。

这就是典型的发布订阅的模式,可以看我这篇文章。

const PENDING = 'PENDING';const FULFILLED = 'FULFILLED';const REJECTED = 'REJECTED';class Promise {  constructor(executor) {    this.status = PENDING;    this.value = undefined;    this.reason = undefined;    // 存放成功的回调    this.onResolvedCallbacks = [];    // 存放失败的回调    this.onRejectedCallbacks= [];    let resolve = (value) => {      if(this.status ===  PENDING) {        this.status = FULFILLED;        this.value = value;        // 依次将对应的函数执行        this.onResolvedCallbacks.forEach(fn=>fn());      }    }     let reject = (reason) => {      if(this.status ===  PENDING) {        this.status = REJECTED;        this.reason = reason;        // 依次将对应的函数执行        this.onRejectedCallbacks.forEach(fn=>fn());      }    }    try {      executor(resolve,reject)    } catch (error) {      reject(error)    }  }  then(onFulfilled, onRejected) {    if (this.status === FULFILLED) {      onFulfilled(this.value)    }    if (this.status === REJECTED) {      onRejected(this.reason)    }    if (this.status === PENDING) {      // 如果promise的状态是 pending,需要将 onFulfilled 和 onRejected 函数存放起来,等待状态确定后,再依次将对应的函数执行      this.onResolvedCallbacks.push(() => {        onFulfilled(this.value)      });      // 如果promise的状态是 pending,需要将 onFulfilled 和 onRejected 函数存放起来,等待状态确定后,再依次将对应的函数执行      this.onRejectedCallbacks.push(()=> {        onRejected(this.reason);      })    }  }}

这下再进行测试

const promise = new Promise((resolve, reject) => {  setTimeout(() => {    resolve('成功');  },1000);}).then(  (data) => {    console.log('success', data)  },  (err) => {    console.log('faild', err)  })

1s 后输出了:

JavaScript怎么实现手写promise

说明成功啦

then的链式调用

这里就不分析细节了,大体思路就是每次 .then 的时候重新创建一个 promise 对象并返回 promise,这样下一个 then 就能拿到前一个 then 返回的 promise 了。

const PENDING = 'PENDING';const FULFILLED = 'FULFILLED';const REJECTED = 'REJECTED';const resolvePromise = (promise2, x, resolve, reject) => {  // 自己等待自己完成是错误的实现,用一个类型错误,结束掉 promise  Promise/A+ 2.3.1  if (promise2 === x) {     return reject(new TypeError('Chaining cycle detected for promise #<Promise>'))  }  // Promise/A+ 2.3.3.3.3 只能调用一次  let called;  // 后续的条件要严格判断 保证代码能和别的库一起使用  if ((typeof x === 'object' && x != null) || typeof x === 'function') {     try {      // 为了判断 resolve 过的就不用再 reject 了(比如 reject 和 resolve 同时调用的时候)  Promise/A+ 2.3.3.1      let then = x.then;      if (typeof then === 'function') {         // 不要写成 x.then,直接 then.call 就可以了 因为 x.then 会再次取值,Object.defineProperty  Promise/A+ 2.3.3.3        then.call(x, y => { // 根据 promise 的状态决定是成功还是失败          if (called) return;          called = true;          // 递归解析的过程(因为可能 promise 中还有 promise) Promise/A+ 2.3.3.3.1          resolvePromise(promise2, y, resolve, reject);         }, r => {          // 只要失败就失败 Promise/A+ 2.3.3.3.2          if (called) return;          called = true;          reject(r);        });      } else {        // 如果 x.then 是个普通值就直接返回 resolve 作为结果  Promise/A+ 2.3.3.4        resolve(x);      }    } catch (e) {      // Promise/A+ 2.3.3.2      if (called) return;      called = true;      reject(e)    }  } else {    // 如果 x 是个普通值就直接返回 resolve 作为结果  Promise/A+ 2.3.4      resolve(x)  }}class Promise {  constructor(executor) {    this.status = PENDING;    this.value = undefined;    this.reason = undefined;    this.onResolvedCallbacks = [];    this.onRejectedCallbacks= [];    let resolve = (value) => {      if(this.status ===  PENDING) {        this.status = FULFILLED;        this.value = value;        this.onResolvedCallbacks.forEach(fn=>fn());      }    }     let reject = (reason) => {      if(this.status ===  PENDING) {        this.status = REJECTED;        this.reason = reason;        this.onRejectedCallbacks.forEach(fn=>fn());      }    }    try {      executor(resolve,reject)    } catch (error) {      reject(error)    }  }  then(onFulfilled, onRejected) {    //解决 onFufilled,onRejected 没有传值的问题    //Promise/A+ 2.2.1 / Promise/A+ 2.2.5 / Promise/A+ 2.2.7.3 / Promise/A+ 2.2.7.4    onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : v => v;    //因为错误的值要让后面访问到,所以这里也要跑出个错误,不然会在之后 then 的 resolve 中捕获    onRejected = typeof onRejected === 'function' ? onRejected : err => { throw err };    // 每次调用 then 都返回一个新的 promise  Promise/A+ 2.2.7    let promise2 = new Promise((resolve, reject) => {      if (this.status === FULFILLED) {        //Promise/A+ 2.2.2        //Promise/A+ 2.2.4 --- setTimeout        setTimeout(() => {          try {            //Promise/A+ 2.2.7.1            let x = onFulfilled(this.value);            // x可能是一个proimise            resolvePromise(promise2, x, resolve, reject);          } catch (e) {            //Promise/A+ 2.2.7.2            reject(e)          }        }, 0);      }      if (this.status === REJECTED) {        //Promise/A+ 2.2.3        setTimeout(() => {          try {            let x = onRejected(this.reason);            resolvePromise(promise2, x, resolve, reject);          } catch (e) {            reject(e)          }        }, 0);      }      if (this.status === PENDING) {        this.onResolvedCallbacks.push(() => {          setTimeout(() => {            try {              let x = onFulfilled(this.value);              resolvePromise(promise2, x, resolve, reject);            } catch (e) {              reject(e)            }          }, 0);        });        this.onRejectedCallbacks.push(()=> {          setTimeout(() => {            try {              let x = onRejected(this.reason);              resolvePromise(promise2, x, resolve, reject)            } catch (e) {              reject(e)            }          }, 0);        });      }    });    return promise2;  }}

Promise.all

核心就是有一个失败则失败,全成功才进行 resolve

Promise.all = function(values) {  if (!Array.isArray(values)) {    const type = typeof values;    return new TypeError(`TypeError: ${type} ${values} is not iterable`)  }  return new Promise((resolve, reject) => {    let resultArr = [];    let orderIndex = 0;    const processResultByKey = (value, index) => {      resultArr[index] = value;      if (++orderIndex === values.length) {          resolve(resultArr)      }    }    for (let i = 0; i < values.length; i++) {      let value = values[i];      if (value && typeof value.then === 'function') {        value.then((value) => {          processResultByKey(value, i);        }, reject);      } else {        processResultByKey(value, i);      }    }  });}

关于“JavaScript怎么实现手写promise”这篇文章的内容就介绍到这里,感谢各位的阅读!相信大家对“JavaScript怎么实现手写promise”知识都有一定的了解,大家如果还想学习更多知识,欢迎关注编程网精选频道。

--结束END--

本文标题: JavaScript怎么实现手写promise

本文链接: https://www.lsjlt.com/news/357115.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • JavaScript怎么实现手写promise
    这篇文章主要介绍了JavaScript怎么实现手写promise的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇JavaScript怎么实现手写promise文章都会有所收获,下面我们一起来看看吧。需求我们先来总...
    99+
    2023-07-06
  • JavaScript实现手写promise的示例代码
    目录背景需求then的链式调用Promise.all背景 promise 作为前端开发中常用的函数,解决了 js 处理异步时回调地狱的问题,大家应该也不陌生了,今天来学习一下 pro...
    99+
    2023-05-15
    JavaScript手写promise JavaScript promise
  • JavaScript面试必考之实现手写Promise
    目录Promise手写框架完整代码测试resolverejectPromise手写 Promise作为面试必考题,Promise的手写也是面试官必问的问题,所以对于Promise我们...
    99+
    2022-12-08
    JavaScript实现手写Promise JavaScript手写Promise JavaScript Promise
  • 怎么使用JavaScript手写一个Promise
    这篇文章主要介绍“怎么使用JavaScript手写一个Promise”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“怎么使用JavaScript手写一个Promise”文章能帮助大家解决问题。Prom...
    99+
    2023-07-02
  • JavaScript手写Promise核心原理
    目录准备完善 resolve/rejectthen异步处理链式调用边界处理catch优化后完整代码准备 首先,promise 有三种状态:pending fulf...
    99+
    2024-04-02
  • 万字详解JavaScript手写一个Promise
    目录前言Promise核心原理实现Promise的使用分析MyPromise的实现在Promise中加入异步操作实现then方法的多次调用实现then的链式调用then方法链式调用识...
    99+
    2024-04-02
  • JavaScript怎么实现简易的Promise对象
    这篇“JavaScript怎么实现简易的Promise对象”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“JavaScript...
    99+
    2023-07-04
  • JavaScript面试必备技巧之手写一个Promise
    目录基本实现实现resolve和reject状态不可变then其他方法很多同学在面试的时候都会被要求手写一个Promise,那么今天我总结了一些手写Promise的方法,可以跟着我的...
    99+
    2023-02-08
    JavaScript实现手写Promise JavaScript手写Promise JavaScript Promise
  • JavaScript Promise怎么用
    今天小编给大家分享一下JavaScript Promise怎么用的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我...
    99+
    2024-04-02
  • JavaScript实现Promise流程详解
    目录构造函数then 和 catch方法解决异步问题all和race方法构造函数 首先我们来看一下我们是如何使用promise的,我们在实例化对象是这么使用的: let p1...
    99+
    2024-04-02
  • JavaScript中Promise怎么用
    这篇文章主要为大家展示了“JavaScript中Promise怎么用”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“JavaScript中Promise怎么用”这...
    99+
    2024-04-02
  • JavaScript自定义Promise实现流程
    目录1. 初始结构2. 定义状态3. this指向4. then 方法5. 执行异常6. 支持异步(重头戏1)7. 回调保存(重头戏2)8. 重难点解读9. 链式功能(重头戏3)1....
    99+
    2022-11-13
    JavaScript Promise JavaScript Promise原理 JS Promise
  • 怎么构造JavaScript Promise
    这篇“怎么构造JavaScript Promise”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看...
    99+
    2024-04-02
  • JavaScript Promise怎么使用
    今天小编给大家分享一下JavaScript Promise怎么使用的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面...
    99+
    2024-04-02
  • JavaScript怎么使用Promise实现并发请求数限制
    本篇内容主要讲解“JavaScript怎么使用Promise实现并发请求数限制”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“JavaScript怎么使用Promise实现并发请求数限制”吧!没有...
    99+
    2023-07-06
  • 怎么实现Promise/A+规范
    这篇文章给大家介绍怎么实现Promise/A+规范,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。我一度以为自己很懂Promise,直到前段时间尝试去实现Promise/A+规范时,才发...
    99+
    2024-04-02
  • 怎么写出符合Promise/A+ 规范Promise的源码
    这篇文章主要介绍“怎么写出符合Promise/A+ 规范Promise的源码”,在日常操作中,相信很多人在怎么写出符合Promise/A+ 规范Promise的源码问题上存在疑惑,小编查阅了各式资料,整理出...
    99+
    2024-04-02
  • JavaScript的Promise对象怎么用
    这篇文章主要讲解了“JavaScript的Promise对象怎么用”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“JavaScript的Promise对象怎么...
    99+
    2024-04-02
  • JavaScript实现一个Promise队列小工具
    目录摘要思考实现总结摘要 在百度的解释中,队列是一种特殊的线性表,特殊之处在于它只允许在表的前端进行删除操作,而在表的后端进行插入操作,和栈一样,队列是一种操作受限制的线性表。进行插...
    99+
    2024-04-02
  • JavaScript的Promise类怎么使用
    这篇文章主要介绍了JavaScript的Promise类怎么使用的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇JavaScript的Promise类怎么使用文章都会有所收获,下...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作