
回调地狱,代码难以维护, 常常第一个的函数的输出是第二个函数的输入这种现象,是为处理异步操作函数里的嵌套回调(callback hell)问题,代码臃肿,可读性差,只能在回调里解决异常
promise可以支持多个并发的请求,获取并发请求中的数据
promise可以处理可读性的问题,异步的嵌套带来的可读性的问题,它是由异步的运行机制引起的,这样的代码读起来会非常费劲
promise可以处理信任问题,对于回调过早、回调过晚或者没有调用和回调次数太少或者太多,因为promise只能决议一次,决议值只能有一个,决议之后无法改变,任何then中的回调也只会被调用一次,所以这就保证了Promise可以处理信任问题
Promise 处理的痛点还有其余方法可以处理,比方setTimeout、事件监听、回调函数、Generator函数,async/await
setTimeout:缺点不准确,只是确保在肯定时间后加入到任务队列,并不保证立马执行。只有执行引擎栈中的代码执行完毕,主线程才会去读取任务队列
事件监听:任务的执行不取决于代码的顺序,而取决于某个事件能否发生
Generator函数尽管将异步操作表示得很简洁,但是流程管理却不方便(即何时执行第一阶段、何时执行第二阶段)。即如何实现自动化的流程管理
async/await
类方法,该方法返回一个以 value 值解析后的 Promise 对象
假如这个值是个 thenable(即带有 then 方法),返回的 Promise 对象会“跟随”这个 thenable 的对象,采用它的最终状态(指 resolved/rejected/pending/settled)
假如传入的 value 本身就是 Promise 对象,则该对象作为 Promise.resolve 方法的返回值返回
其余情况以该值为成功状态返回一个 Promise 对象
类方法,且与 resolve 唯一的不同是,返回的 promise 对象的状态为 rejected
实例方法,为 Promise 注册回调函数,函数形式:fn(vlaue){},value 是上一个任务的返回结果,then 中的函数肯定要 return 一个结果或者者一个新的 Promise 对象,才可以让之后的then 回调接收
实例方法,捕获异常,函数形式:fn(err){}, err 是 catch 注册 之前的回调抛出的异常信息
类方法,多个 Promise 任务同时执行,返回最先执行结束的 Promise 任务的结果,不论这个 Promise 结果是成功还是失败
类方法,多个 Promise 任务同时执行
假如一律成功执行,则以数组的方式返回所有 Promise 任务的执行结果。 假如有一个 Promise 任务 rejected,则只返回 rejected 任务的结果
promise可以支持多个并发的请求,获取并发请求中的数据
promise可以处理可读性的问题,异步的嵌套带来的可读性的问题,它是由异步的运行机制引起的,这样的代码读起来会非常费劲
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); }} 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; } }); };promise一旦执行,无法中途取消
promise的错误无法在外部被捕捉到,只能在内部进行预判解决
promise的内如何执行,监测起来很难
实例代码:
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
求点赞,求关注~