大佬教程收集整理的这篇文章主要介绍了Promise 规范解读及实现细节 (一),大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。
这两个是指两个队列,脚本整体代码、setTimeout、seTinterval、setImmediate、I/O、的回调及UI渲染都会被加入到 macrotask 队列中,process.nextTick回调、Promise(浏览器实现)、MutationObserver回调都会被加入到microtask队列。
1 当浏览器进入事件循环时,先去看macrotask中有没有具备执行条件的任务
3 没有则去看microtask队列有没有具备执行条件的任务
4 有则全部执行(全部执行)
5 去更新页面
6 然后重复以上行为
Promise主要的@L_772_5@是将异步执行结果保存起来,从而使得我们不再用回调的方式去处理异步任务的结果,我们通过一个回调将异步任务的结果保存起来,在以后某个时刻通过各种姿势去使用它new romise(excutor).then(function(result)}).then(function(result){});的方式去执行异步任务,Promise 是通过回调来实现的,但它将回调统一,使得我们不在去直接接触回调,用看似有点像同步的方式去写异步任务,也就仅仅是这样而已,并没有什么新东西,这种同步方式只能说是类似同步,下一篇会讲写法更接近同步、更加有建术的 generator 。
function Promise(excutor) {
var self = this; var status = 'PENDING'; //Promise的当前状态 var data = undefined; //当前excutor(就是用户的异步任务)的执行结果 self.onResolvedCallBACk = []; //excutor 执行成功后回调函数队列 self.onRejectedCallBACk = []; //excutor 执行失败后回调函数队列 function resolve(value) { // TUDO 异步任务执行成功后的行为 // 1 改变当前promise的status值 调用该方法 PENDING->RESOLVED // 2 执行onResolvedCallBACk队列里面的所有回调函数并传递异步任务的异步处理结果 // onResolvedCallBACk[i](data) } function reject(value) { // TUDO 异步任务执行失败后的行为 // 1 改变当前promise的status值 调用该方法 PENDING->REjeCTED // 2 执行onRejectedCallBACk队列里面的所有回调函数并传递异步任务的异步处理结果 // onRejectedCallBACk[i](data) } excutor(resolve,reject); //执行用户添加的任务 } Promise.prototype.then = function (onResolved,onRejected) { // onResolved异步任务执行成功的回调 // onRejected异步任务执行失败后的回调 } 看起来就是这样的 具体使用方式 new Promise(function(resolve,reject){ setTimeout(function(result){ // resolve(result) 或reject(result) 根据返回值决定 //这里我们确实还是写了回调,但是我们在回调里面没有做太多的事件 //仅仅是传递了异步处理结果 想想如果,我们在这里又要做依赖于result的 //异步任务会怎样,回调地狱,代码结构混乱,不容易读 }); }).then(function(result){}) //这里的result是从上面的那个回调里面传递的,是同一个值
function Promise(excutor) { var self = this; var status = 'PENDING'; //Promise的当前状态 var data = undefined; //当前excutor(就是用户的异步任务)的执行结果 self.onResolvedCallBACk = []; //excutor 执行成功后回调函数队列 self.onRejectedCallBACk = []; //excutor 执行失败后回调函数队列 function resolve(value) { // TUDO 异步任务执行成功后的行为 if(self.status === 'PENDING') { self.status = 'REjeCTED'; // 改变当前promise的status值 调用该方法 PENDING->RESOLVED self.data = value; // 更新当前的data for(var i in self.onResolvedCallBACk) { self.onResolvedCallBACk[i](self.data); //执行onResolvedCallBACk队列里面的所有回调函数并传递异步任务的异步处理结果 } } } function reject(reson) { // TUDO 异步任务执行失败后的行为 if(self.status === 'PENDING') { self.status = 'REjeCTED'; self.data = reson; for(var i in self.onRejectedCallBACk) { self.onRejectedCallBACk[i](self.data); } } } try { excutor(resolve.bind(this),reject.bind(this)); //执行用户添加的任务 /*这里为什么要通过通过 bind 来绑定上下文呢,主要是 resolve 依赖当 前 promise的内部属性,在excutor函数体内,我们是通过 resolve(data) 或者reject(reson) 的方式来调用通过这种方式调用 在非严格模式 resolve或reject的上下文是windows,在严格模式下是undefined*/ } catch(E) { reject.bind(this)(E); //出现异常则通过reject向后传递 } }
(2) then 方法的实现
then方法应当具备如下@L_772_5@
(1) then方法必须返回一个Promise对象,也就是,对应用户添加的逻辑要进行包装
(2) 同一个对象可多次调用then来添加逻辑,并且会按照添加顺序执行
//例如: var promise = new Promise(function(resolve,reject) { //异步操作 并且在回调中调用了 resolve或者 reject将异步处理结果传递出去 }); promise.then(function(data){ //对异步结果data进行操作 }); promise.then(function(data){ //对异步结果data进行操作 }); //promise是同一个对象
(3) 可以链式调用
//例如: new Promise(function(resolve,reject){ //异步操作 并且在回调中调用了 resolve或者 reject将异步处理结果传递出去 }).then(function(data){}).then(function(data){});
这里第一次和第二次调用then的对象是两个不同的对象,这里要注意
[1] 如果第一个then的参数也是一个Promise那么在第二个then的中会得到第一个then的处理结果 [2] 如果第一个then的参数是一个函数并且有返回值,则在第二个then中会接收到这个返回值 [3] 其它情况下都会得到通过 new Promise(fn) 这里这个异步fn的处理结果
(4) 我们写的Promise 要和所有符合Promise规范的 Promise 能协同工作(例如浏览器自带的、第三方库的)
/** *@parms onResolved 任务成功时执行的回调 *@parms onRejected 任务失败时执行的回调 */ Promise.prototype.then = function(onResolved,onRejected) { var self = this; var promiseThen; //then方法返回的promise //如果 onResolved或onRejected 不是函数我们忽略它,并且添加一个用于传递异步结果得函数 onResolved = typeof onResolved ==='function' ? onResolved : function(value) {resolve(value);} onRejected = typeof onRejected ==='function' ? onRejected : function(reson) {resolve(reson);} /*如果在调用then添加依赖于异步处理结果的时候,异步任务已经执行完了,那么 用异步的结果执行then里面添加的任务*/ if(self.status === 'RESOLVED') { //这里要将then里面要添加的任务包装成一个Promise,返回Promise 是为了(3)中的链式调用 return promiseThen = new Promise(function(resolve,reject) { try { //执行then添加的任务 var x = onResolved(self.data); if(x instanceof PromisE) { /*如果then添加的任务有返回值,并且返回值是Promise对象 则让promiseThen去接受x的状态和data值注意,这里将 promiseThen的resolve,和reject作为x的then参数传入,这 样当promiseThen的resolve和reject会在适当的时候被调用 从而使得promiseThen接受了x的状态和data值Promise的不 同对象之间能实现相互影响,是通过将自己的resolve和 reject添加到其它对象中*/ x.then(resolve,reject); } else resolve(X); //如果x不是Promise使用X的值作为promiseThen的结果 } catch (E) { reject(E); } }); } //和上面逻辑相同 if(self.status === 'REjeCTED') { return promiseThen = new Promise(function(resolve,reject){ try { var x = onRejected(self.data); if(x instanceof PromisE){ x.then(resolve,reject); } }catch(E) { reject(E); } }); } if(self.status === 'PENDING') { //当前Promise的异步任务没有执行完,则将then里面的异步任务 包装后放入队列 //包装方法和上面一样,区别是上面立即执行,这里放入回调队列。 return promiseThne = new Promise(function() { self.onResolvedCallBACk.push(function(){ try { var x = onResolved(self.data); if(x instanceof PromisE) { x.then(resolve,reject); } catch(E) { reject(E); } } }); self.onRejectedCallBACk.pudh(function(){ try { var x = onRejected(self.data); if(x instanceof PromisE) { x.then(resolve,reject); } catch(E) { reject(E); } } }); }); } }
写到这里Promise具体实现的 (1)、(2)、(3)的@L_772_5@已经完成了,也就是如果不考虑与其它的Promise交互那么Promise的原理已经说清楚了,本来打算一篇文章写完,但是篇幅太长,所以打算分两篇文章来写,下一篇是generator,之后我会按照规范将(4)部分实现。
以上是大佬教程为你收集整理的Promise 规范解读及实现细节 (一)全部内容,希望文章能够帮你解决Promise 规范解读及实现细节 (一)所遇到的程序开发问题。
如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。
本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。