对于promise的常见面试题总结分析

作者 : 开心源码 本文共6016个字,预计阅读时间需要16分钟 发布时间: 2022-05-12 共204人阅读

1、理解 Promise 吗?

  • 理解Promise,Promise是一种异步编程的处理方案,有三种状态,pending(进行中)、resolved(已完成)、rejected(已失败)。当Promise的状态由pending转变为resolved或者reject时,会执行相应的方法
  • Promised的特点是只有异步操作的结果,可以决定当前是哪一种状态,任务其余操作都无法改变这个状态,也是“Promise”的名称的由来,同时,状态一旦改变,就无法再次改变状态

2、Promise 处理的痛点是什么?

Promise处理的痛点:

  • 回调地狱,代码难以维护, 常常第一个的函数的输出是第二个函数的输入这种现象,是为处理异步操作函数里的嵌套回调(callback hell)问题,代码臃肿,可读性差,只能在回调里解决异常

  • promise可以支持多个并发的请求,获取并发请求中的数据

  • promise可以处理可读性的问题,异步的嵌套带来的可读性的问题,它是由异步的运行机制引起的,这样的代码读起来会非常费劲

  • promise可以处理信任问题,对于回调过早、回调过晚或者没有调用和回调次数太少或者太多,因为promise只能决议一次,决议值只能有一个,决议之后无法改变,任何then中的回调也只会被调用一次,所以这就保证了Promise可以处理信任问题

3、Promise 处理的痛点还有其余方法可以处理吗?假如有,请列举。

  • Promise 处理的痛点还有其余方法可以处理,比方setTimeout、事件监听、回调函数、Generator函数,async/await

  • setTimeout:缺点不准确,只是确保在肯定时间后加入到任务队列,并不保证立马执行。只有执行引擎栈中的代码执行完毕,主线程才会去读取任务队列

  • 事件监听:任务的执行不取决于代码的顺序,而取决于某个事件能否发生

  • Generator函数尽管将异步操作表示得很简洁,但是流程管理却不方便(即何时执行第一阶段、何时执行第二阶段)。即如何实现自动化的流程管理

  • async/await

4、Promise 如何使用?

  • 创造一个Promise实例
  • Promise实例生成以后,可以用then方法分别指定resolved状态和rejected状态的回调函数
  • 可用Promise的try和catch方法预防异常

5、Promise 常用的方法有哪些?它们的作用是什么?

Promise.resolve(value)

类方法,该方法返回一个以 value 值解析后的 Promise 对象
假如这个值是个 thenable(即带有 then 方法),返回的 Promise 对象会“跟随”这个 thenable 的对象,采用它的最终状态(指 resolved/rejected/pending/settled
假如传入的 value 本身就是 Promise 对象,则该对象作为 Promise.resolve 方法的返回值返回
其余情况以该值为成功状态返回一个 Promise 对象

Promise.reject

类方法,且与 resolve 唯一的不同是,返回的 promise 对象的状态为 rejected

Promise.prototype.then

实例方法,为 Promise 注册回调函数,函数形式:fn(vlaue){}value 是上一个任务的返回结果,then 中的函数肯定要 return 一个结果或者者一个新的 Promise 对象,才可以让之后的then 回调接收

Promise.prototype.catch

实例方法,捕获异常,函数形式:fn(err){}, err 是 catch 注册 之前的回调抛出的异常信息

Promise.race

类方法,多个 Promise 任务同时执行,返回最先执行结束的 Promise 任务的结果,不论这个 Promise 结果是成功还是失败

Promise.all

类方法,多个 Promise 任务同时执行
假如一律成功执行,则以数组的方式返回所有 Promise 任务的执行结果。 假如有一个 Promise 任务 rejected,则只返回 rejected 任务的结果

6、Promise 在事件循环中的执行过程是怎么的?

事件循环

  • 从代码执行顺序的角度来看,程序最开始是按代码顺序执行代码的,遇到同步任务,立刻执行;遇到异步任务,则只是调用异步函数发起异步请求。此时,异步任务开始执行异步操作,执行完成后到消息队列中排队。程序按照代码顺序执行完毕后,查询消息队列中能否有等待的消息。假如有,则按照次序从消息队列中把消息放到执行栈中执行。执行完毕后,再从消息队列中获取消息,再执行,不断重复。因为主线程不断的重复取得消息、执行消息、再取消息、再执行

promise的事件循环

  • Promise在初始化时,传入的函数是同步执行的,而后注册 then 回调。注册完之后,继续往下执行同步代码,在这之前,then 中回调不会执行。同步代码块执行完毕后,才会在事件循环中检测能否有可用的 promise 回调,假如有,那么执行,假如没有,继续下一个事件循环

7、Promise 的业界实现都有哪些?

  • promise可以支持多个并发的请求,获取并发请求中的数据

  • promise可以处理可读性的问题,异步的嵌套带来的可读性的问题,它是由异步的运行机制引起的,这样的代码读起来会非常费劲

8、能不能手写一个 Promise 的 polyfill?

  • Promsie的 polyfill 的源码实现
    实例代码:
function Promise(fn){        //  说明 Promise必需以构造函数形式被调用        if(!(this instanceof  Promise))            throw  new TypeError('Promises must be constructed via new');        // 说明 Promise的唯一参数fn必需是函数类型        if(typeof fn !== "function")            throw new TypeError('not a function');        // _state属性定义了Promise的状态        // Promise有pending、fulfilled、rejected三种状态,分别对应_state值为0、1、2        this._state = 0;        // _handled属性的类型为Boolean,初始值为false,其代表Promise能否被解决        this._handled = false;        //  _value属性的类型为Promise或者undefined,初始值为undefined        this._value = undefined;        // _deferreds属性的类型为Array,初始值为空数组,数组中存放的值为Function        this._deferreds = [];        // 将Promise的参数fn与代表当前对象的this作为参数,deResolve函数进行调用        doResolve(fn,this);    }function doResolve(fn, self) {        // done变量的作用就是为了防止resolve()和reject()被同时调用        //  Promise的状态只能从pending->fulfilled或者pending->rejected        var done = false;        try {            //  fn的构造函数的参数,new Promise传入的回调函数  fn(resolve,reject);            fn(                    function(value) {                        if (done) return;                        // done变量为true则直接退出函数                        done = true;                        resolve(self, value);                    },                    function(reason) {                        if (done) return;                        done = true;                        reject(self, reason);                    }            );        } catch (ex) {            // 调用Promsie构造函数假如抛出异常,则Promise就会变为rejected状态            if (done) return;            done = true;            reject(self, ex);        }}
  • Promise 的 polyfill的实现
    实例代码:
 const promiseStatusSymbol = Symbol("PromiseStatus");    const promiseValueSymbol = Symbol("PromiseValue");    // pending、fulfilled、rejected    const status = {        pending:"pending",        fulfilled:"fulfilled",        rejected:"rejected"    };    const transition = function(status){    /*    var self = this;        return function(value){            this[promiseStatusSymbol] = status;            this[promiseValueSymbol] = value;        }*/       return (value) => {            this[promiseValueSymbol] = value;            setStatus.call(this,status);        }    };    // 对于状态的改变进行控制    // 假如状态从 pending 到 fulfilled, 那么调用链式的下一个fulfilled函数    // 假如状态从 pending 到 rejected, 那么调用链式的下一个rejected函数    const setStatus = function(status){       this[promiseStatusSymbol] = status;       if(status === status.fulfilled){           this.deps.resolver && this.deps.resolver();       }else if( status === status.rejected){           this.deps.rejector && this.deps.rejector();       }    };    // 当开始异步操作的时候,还没有结果的时候,处于pending状态,而后再改变为成功或者者是失败的状态    const promise = function(resolver){      if(typeof  resolver !== "function"){          throw new TypeError("parameter 1 must be a function");      }        this[promiseStatusSymbol] = status.pending;        this[promiseValueSymbol] = [];        this.deps = [];        resolver(            //  返回函数resolve和reject            //  这两个函数会分别对当期的Promise的状态和值进行修改,修改成功或者者失败            transition.call(this,status.fulfilled),            transition.call(this.status.rejected)        );    };    // promise的链式调用主要是一个对于依赖进行依次收集的过程,then方法是增加依赖,不是执行回调函数    promise.prototype.then = function(fulfilled,rejected){        const self = this;        return promise(function(resolve,reject){           const callback = function () {               // 回调函数执行的返回值需要保存下来               // 在链式调用的时候,参数应该传递给链式调用的下一个               const resoleValue = fulfilled(self[promiseValueSymbol]);              // resolve(resoleValue);              // 返回值相当于是一个thenable对象,改变直接调用then方法,获取一个返回值              if(resoleValue && typeof resoleValue.then === "function"){                  // 内嵌promise,将得到的值绑定在promise的依赖中                  resoleValue.then(function(data){                      resolve(data);                  },function(err){                      reject(err);                  });              }else{                  // then 方法链式调用的连接点                  // 在初始化状态或者者上一次promise的状态发生改变的时候,调用当前promise成功的方法                  //  对当前promise的状态进行改变,以及进行调用链式的下一个promise的回调                  resolve(resoleValue);              }           };           const errCallback = function(){               const rejectValue = rejected(self[promiseValueSymbol]);               reject(rejectValue);           };           // 对于promise的状态解决           // 假如上一个promise在执行then方法之前就已经完成了,那么下一个promise对应的回调应该立即执行           // 假如当前的状态为pending,说明promise的异步操作还没有决议,          //成功和失败的回调应该保存在之前的promise的依赖之中            if(self[promiseStatusSymbol] === status.fulfilled){               return callback();           }else if(self[promiseStatusSymbol] === status.rejected){               return errCallback();           }else if(self[promiseStatusSymbol] === status.pending){               self.deps.resolver = callback;               self.deps.rejector = errCallback;           }        });    };

9、 Promise的问题?处理办法?

promise的问题为:

  • promise一旦执行,无法中途取消

  • promise的错误无法在外部被捕捉到,只能在内部进行预判解决

  • promise的内如何执行,监测起来很难

处理办法

  • 正是由于这些起因,ES7引入了更加灵活多变的async,await来解决异步

10、手写Promise与ajax的结合?

实例代码:

function promiseGet (url) {  return new Promise((resolve, reject) => {    let xhr = new XMLHttpRequest()    xhr.open('GET', url, true)    xhr.onreadystatechange = function () {      if (this.readyState === 4) {        if (this.status === 200) {          resolve(this.responseText,this)        } else {          let resJson = {            code: this.status,            response: this.response          }          reject(resJson, this)        }      }    }  })

作者:旧城tk
链接:https://juejin.im/post/5d10dfeb6fb9a07ecc44921c

求点赞,求关注~

说明
1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长!
2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系管理员处理!
6. 本站资源售价只是摆设,本站源码仅提供给会员学习使用!
7. 如遇到加密压缩包,请使用360解压,如遇到无法解压的请联系管理员
开心源码网 » 对于promise的常见面试题总结分析

发表回复