class Promise{constructor(excutor){this.value = '';this.reason = '';this.status = 'padding'this.onFulfilledCallback = []this.onRejectedCallback = []let resolve = (value)=>{/*2.这个判断是为了status不可逆 只能从 padding转化为 成功或者失败*/if (this.status == 'padding') {this.status = 'fulfilled'this.value = value/*3.当转态改变的时候依次执行队列里面储存的then函数里面对应的回调*/this.onFulfilledCallback.forEach(fn=>{fn()})}};let reject = (reason)=>{/*2.这个判断是为了status不可逆 只能从 padding转化为 成功或者失败*/if (this.status == 'padding') {this.status = 'rejected'this.reason = reason/*3.当转态改变的时候依次执行队列里面储存的then函数里面对应的回调*/this.onRejectedCallback.forEach(fn=>{fn()})}};/*1. 当发生异常是捕获异常 */try{excutor(resolve,reject)}catch (e){reject(e)}}then(onFulfilled,onRejected){//4.防止使用者不传成功或失败回调函数,所以成功失败回调都给了默认回调函数onFulfilled = typeof onFulfilled === "function" ? onFulfilled : value => value;onRejected = typeof onRejected === "function" ? onRejected : error => { throw error };let newPromise;if(this.status == 'fulfilled'){return newPromise = new Promise((resolve,reject)=>{setTimeout(()=>{try{let x = onFulfilled(this.value)this.resolvePromise(newPromise, x, resolve, reject);}catch (e){reject(e)}})})}if(this.status == 'rejected'){return newPromise = new Promise((resolve,reject)=>{setTimeout(()=>{try{let x = onRejected(this.reason)this.resolvePromise(newPromise, x, resolve, reject);}catch (e){reject(e)}})})}if(this.status == 'padding'){return newPromise = new Promise((resolve,reject)=> {/*3.当excutor为异步的时候先把then方法里面的回调储存在失败或者成功的队列里面*/this.onFulfilledCallback.push(() => {//这里可以写其他的代码对resolve做一层封装todosetTimeout(()=> {try {let x = onFulfilled(this.value)this.resolvePromise(newPromise, x, resolve, reject);} catch (e) {reject(e)}})})this.onRejectedCallback.push(() => {setTimeout(()=> {try {let x = onRejected(this.reason)this.resolvePromise(newPromise, x, resolve, reject);} catch (e) {reject(e)}})})})}//4.保证链式调用 返回this  这样做虽然能链式调用但是 所有链式调用的回调函数都挂载到同一个对象上 且当后面的then方法执行//的时候promise的状态已经确定会马上执行其对应的回调,并且参数都为this.value这一个值//return this}catch(onRejected){this.then(null,onRejected)}resolvePromise(newPromise,x,resolve,reject){//2.3.1规范,避免循环引用if (newPromise === x) {return reject(new TypeError('Circular reference'));}//called变量主要是用来判断如果resolvePromise函数已经resolve或者reject了,那就不需要在执行下面的resolce或者reject。//设置一个标志位,在执行resolve或者reject其中之一后,讲不能再执行resolve或者reject  eg:resolve();reject()let called = false;if (x != null && ((typeof x === 'object') || (typeof x === 'function'))) {try{let then = x.then;if (typeof then === 'function') {//2.3.3.3 如果 then 是一个函数,以x为this调用then函数,且第一个参数是resolve,第二个参数是rejectthen.call(x, y => {if (called) return;called = true;this.resolvePromise(newPromise, y, resolve, reject);}, error => {if (called) return;called = true;reject(error);})} else {//2.3.3.4 如果 then不是一个函数,则 以x为值fulfill promise。resolve(x);}}catch(e){if (called) return;called = true;reject(e);}}else {resolve(x)}}}
// 执行测试用例需要用到的代码
Promise.deferred = function() {let defer = {};defer.promise = new Promise((resolve, reject) => {defer.resolve = resolve;defer.reject = reject;});return defer;
}
try {module.exports = Promise
} catch (e) {}// 1.npm i -g promises-aplus-tests
// 2.promises-aplus-tests mypromise.js

本面试题为前端常考面试题,后续有机会继续完善。我是歌谣,一个沉迷于故事的讲述者。

欢迎一起私信交流。

“睡服“面试官系列之各系列目录汇总(建议学习收藏)

“约见”面试官系列之常见面试题之第八十四篇之手写promise(建议收藏)相关推荐

  1. “约见”面试官系列之常见面试题之第一百零四篇之vue优点(建议收藏)

    vue的优点: 1.轻量级框架 只关注视图层,是一个构建数据的视图集合,大小只有几十kb Vue.js通过简洁的API提供高效的数据绑定和灵活的组件系统 2.简单易学 国人开发,中文文档,不存在语言障 ...

  2. “约见”面试官系列之常见面试题之第八十九篇之vue生命周期作用(建议收藏)

    那么vue 生命周期有哪些阶段呢 一.创建 1.beforeCreate:这个阶段实例已经初始化,只是数据观察与事件机制尚未形成,不能获取DOM节点(没有data,没有el) 使用场景:因为此时dat ...

  3. “约见”面试官系列之常见面试题之第八十六篇之nexttick(建议收藏)

    一.用途 应用场景:需要在视图更新之后,基于新的视图进行操作. this.$nextTick()方法主要是用在数据改变,dom改变应用场景中.vue中数据和dom渲染由于是异步的,所以,要让dom结构 ...

  4. “约见”面试官系列之常见面试题之第八十五篇之css响应式(建议收藏)

    响应式布局 一个网站能够兼容多个终端,并且在各个终端都可以很好展示体验. 媒体类型 在何种设备或者软件上将页面打开 1 2 3 4 5 6 7 8 9 all:所有媒体 braille:盲文触觉设备 ...

  5. “约见”面试官系列之常见面试题之第八十二篇之MVC(建议收藏)

    MVC设计模式 MVC模式(Model-View-Controller)是软件工程中的一种软件架构模式,把软件系统分为三个基本部分:模型(Model).视图(View)和控制器(Controller) ...

  6. “约见”面试官系列之常见面试题之第七十四篇之v-if和v-for优先级(建议收藏)

    永远不要把 v-if 和 v-for 同时用在同一个元素上. 一般我们在两种常见的情况下会倾向于这样做: 为了过滤一个列表中的项目 (比如 v-for="user in users" ...

  7. “约见”面试官系列之常见面试题之第六十四篇之call和apply区别(建议收藏)

    call和apply用来调用函数,并用指定对象(第一个参数)替换函数的 this 值,同时用指定数组替换函数的参数.注:也可以不指定参数,此时只是单纯的调用函数,如:fun.call() 语法: fu ...

  8. “约见”面试官系列之常见面试题之第五十四篇之语义化标签(建议收藏)

    目录 什么是语义元素? 为什么要语义化? HTML5常用的语义元素 很多面试官会问:谈谈你对 HTML5语义化标签的理解.那么本篇博客专门解答一下这个问题. 什么是语义元素? 语义是指对一个词或者句子 ...

  9. “约见”面试官系列之常见面试题之第八十八篇之什么是vue生命周期(建议收藏)

    我们知道vue是一个构建数据驱动的 web 界面的渐进式框架,那么vue生命周期是什么呢?本篇文章就给大家来介绍一下vue生命周期的内容,希望可以帮助到有需要的朋友. vue生命周期是什么? Vue生 ...

最新文章

  1. GDB调试--以汇编语言为例
  2. 「人民的希望」首批临床结果公布:2/3重症10天内有效改善,一半以上摆脱呼吸机 | 新英格兰医学重磅...
  3. C++三五法则,看看你能不能理解(推荐)
  4. 《深入理解Elasticsearch(原书第2版)》一2.2 查询改写
  5. 大数据与数据挖掘考试题_2017-2019年全国Ⅱ卷高考考点数据分析(理综合)
  6. jquery 获取easyui combobox选中的值
  7. 第7届UBBF在迪拜举办 加强网络设施建设将加速产业发展成为共识
  8. python类方法继承_python类的继承
  9. phpcmsV9 如何开启“会员注册” - 教程篇
  10. mysql数据库中eof_数据库eof
  11. cJSON字符串解析
  12. GAN(生成对抗神经网络 )的一点思考
  13. gopher攻击mysql_从一道CTF题目看Gopher攻击MySql
  14. 【华为面试手撕代码】
  15. 数字接龙 用计算机完成318,微信报名接龙数字如何排列对齐传递
  16. 关于stable diffusion的embedding训练的一篇随笔
  17. Zookeeper详解(五):通过JMX查看Zookeeper信息
  18. PCB中MARK点画法与注意事项
  19. win10登录选项没有PIN,设置了PIN仍然在系统的登录选项中显示[添加],PIN无法使用
  20. app模式会被第三方平台模式取代吗_未来APP将取代移动网站? - 搜外问答

热门文章

  1. AngularJs学习笔记(四)
  2. MyBatis.Net 学习手记
  3. matlab中get和set命令,关于matlab中get和set的用法
  4. 如何用计算机求和,求和计算器
  5. sentinel 不显示项目_Sentinel+Nacos实现资源流控、降级、热点、授权
  6. Linux---进程调度相关命令解析
  7. php7.2 event扩展php_sockets_le_socket错误解决
  8. readdirectorychangesw 链接错误 undeclared identifier 解决方法
  9. CH9102 USB转串口应用体验
  10. [Redux/Mobx] 说说Redux的实现流程