最终答案在一个类库里,地址 https://github.com/yahoo/ypromise 这个类库也有问题,就是下面这道面试题在IE9里实现不一致,类库里还是用了setTimeout。去年尝试用setTimeout(,0)来实现Promise,见Promise的实现原理 ,最后以失败告终。今天前端leader在群里放了一组面试题,最后一题

  1. setTimeout(function() {
  2. console.log(1)
  3. }, 0);
  4. new Promise(function executor(resolve) {
  5. console.log(2);
  6. for( var i=0 ; i<10000 ; i++ ) {
  7. i == 9999 && resolve();
  8. }
  9. console.log(3);
  10. }).then(function() {
  11. console.log(4);
  12. });
  13. console.log(5);

romise 的 then 应当会放到当前 tick 的最后,但是还是在当前 tick 中。因此,应当先输出 5,然后再输出 4 。最后在到下一个 tick,就是 1 。

“2 3 5 4 1”

补充解释是最后一题 Promise 的 4 在 1 前面输出是因为 Promise.then()里面的回调属于 microtask, 会在当前 Event Loop 的最后执行, 而 SetTimeout 内的回调属于 macrotask, 会在下一个 Event Loop 中执行。

这时候忽然发现用setTimeout来实现貌似有问题,然后东哥说当然不能用settimeout实现。promise依赖通知机制,不依赖时间,里面使用了观察者模式。这又给了我新的思路,去

github上搜一下Promise,有一些写好的库,关键词加上中文二字,也会发现简易实现。迷你书提到了一些较好的Promsie实现,真的有不用settimeout来实现的,好好看一下。

找到了另外一篇,promise异步编程的原理  担心作者删掉,就在这儿再贴一份(原文有错误,我这儿改正了),也可参考另外一篇。这篇也存在很大的问题,就是在只能用异步的方法,不能用同步。到底去哪找靠谱的实现呢。

要实现promise对象,首先要考虑几个问题:

1.promise构造函数中要实现异步对象状态和回调函数的剥离,并且分离之后能够还能使回调函数正常执行

2.如何实现链式调用并且管理状态

首先是构造函数:

  1. //全局宏定义
  2. var PENDING = 0;
  3. var FULFILLED = 1;
  4. var REJECTED = 2;
  5. //Promise构造函数
  6. function Promise(fn){
  7. var self = this;
  8. self.state = PENDING;//初始化状态
  9. self.value = null;//存储异步结果的对象变量
  10. self.handlers = [];//存储回调函数,这里没保存失败回调函数,因为这是一个dome
  11. //异步任务成功后处理,这不是回调函数
  12. function fulfill(result){
  13. if(self.state === PENDING){
  14. self.state = FULFILLED;
  15. self.value = result;
  16. for(var i=0;i<self.handlers.length;i++){
  17. self.handlers[i](result);
  18. }
  19.  
  20. }
  21. }
  22.  
  23. //异步任务失败后的处理,
  24. function reject(err){
  25. if(self.state === PENDING){
  26. self.state = REJECTED;
  27. self.value = err;
  28. }
  29. }
  30. fn&&fn(fulfill,reject);
  31.  
  32. };

构造函数接受一个异步函数,并且执行这个异步函数,修改promise对象的状态和结果。

回调函数方法then:

  1. //使用then方法添加回调函数,把这次回调函数return的结果当做return的promise的resolve的参数
  2. Promise.prototype.then = function(onResolved, onRejected){
  3. var self = this;
  4. return new Promise(function(resolve, reject){
  5. var onResolvedFade = function(val){
  6. var ret = onResolved?onResolved(val):val;//这一步主要是then方法中传入的成功回调函数通过return来进行链式传递结果参数
  7. if(ret instanceof Promise){//回调函数返回值也是promise的时候
  8. ret.then(function(val){
  9. resolve(val);
  10. });
  11. }
  12. else{
  13. resolve(ret);
  14. }
  15. };
  16. var onRejectedFade = function(val){
  17. var ret = onRejected?onRejected(val):val;
  18. reject(ret);
  19. };
  20. self.handlers.push(onResolvedFade);
  21. if(self._status === FULFILLED){
  22. onResolvedFade(self._value);
  23. }
  24.  
  25. if(self._status === REJECTED){
  26. onRejectedFade(self._value);
  27. }
  28. });
  29. }

通过上面的代码可以看出,前面提出的2个问题得到了解决,1.在promise对象中有3个属性,state,value,handlers,这3个属性解决了状态和回调的脱离,并且在调用then方法的时候才将回调函数push到handlers属性上面(此时state就是1,可以在后面的代码中执行onResolve)2.链式调用通过在then方法中返回的promise对象实现,并且通过onResolvedFade将上一个回调的返回值当做这次的result参数来执行进行传递。

测试代码:

  1. function async(value){
  2. var pms = new Promise(function(resolve, reject){
  3. setTimeout(function(){
  4. resolve(value);;
  5. }, 1000);
  6. });
  7. return pms;
  8. }
  9. async(1).then(function(result){
  10. console.log('the result is ',result);//the result is 2
  11. return result;
  12. }).then(function(result){
  13. console.log(++result);//
  14. });

 

探究Promise的实现的更多相关文章

  1. 异步编程之Promise(2):探究原理

    异步编程系列教程: (翻译)异步编程之Promise(1)--初见魅力 异步编程之Promise(2):探究原理 异步编程之Promise(3):拓展进阶 异步编程之Generator(1)--领略魅 ...

  2. JavaScript 执行机制

    一.宏任务与微任务 macro-task(宏任务):包括整体代码script,setTimeout,setInterval micro-task(微任务):Promise,process.nextTi ...

  3. 转载---JavaScript执行机制

    很好的一篇文章,原地址 JavaScript执行机制 这一次,彻底弄懂 JavaScript 执行机制 本文的目的就是要保证你彻底弄懂javascript的执行机制,如果读完本文还不懂,可以揍我. 不 ...

  4. 【js】javaScript 执行机制

    javascript 是一门单线程语言(按照语句一行一行的执行) let a = '1'; console.log(a); let b = '2'; console.log(b); 这样子正常执行是没 ...

  5. 这一次,彻底弄懂 JavaScript 执行机制

    本文转自https://juejin.im/post/59e85eebf265da430d571f89#heading-4 本文的目的就是要保证你彻底弄懂javascript的执行机制,如果读完本文还 ...

  6. js 同步 异步 宏任务 微任务 文章分享

    分享一篇 写的很好的 宏任务 微任务  同步异步的文章 文章原地址: https://juejin.im/post/59e85eebf265da430d571f89 这一次,彻底弄懂 JavaScri ...

  7. Promise学习探究

    学习熟知吧,原理还是继续吧 例子1: var isGeted; function getRet(){ return new Promise(function(resolve, reject) { // ...

  8. Promise 原理探究及其简单实现

    可移步 http://donglegend.com/2016/09/11/promise%E5%8E%9F%E7%90%86%E6%8E%A2%E7%A9%B6/ 观看 Promise是个什么玩意,大 ...

  9. Promise原理与实现探究的一种思路

    写在前面 这个文章,展现的是一个实现Promise的思路,以及如何发现和处理问题的情境. 从现有的Promise分析 如果我们想要自己实现一个简单的Promise,那现有规范规定的Promise肯定是 ...

随机推荐

  1. 杭州"人才新政22条" 硕士来杭工作一次性补贴2万元

    转载自原文杭州"人才新政22条" 硕士来杭工作一次性补贴2万元 2016-11-8 继去年1月推出“人才新政27条”后,杭州在引才上又将有新动作.在昨天举行的2016浙江·杭州国际 ...

  2. js课程 4-12 js中正则表达式如何使用

    js课程 4-12 js中正则表达式如何使用 一.总结 一句话总结: 1.js正则表达式手册取哪里找? w3cschool或者菜鸟教程->找到js正则表达式->完整的RegExp参考手册这 ...

  3. jQuery笔记---选择器

    查找API,jQuery选择器,定位标签 1.基本选择器 id定位标签 class属性定位标签 标签名定位标签 2.举例 <html> <head> <meta http ...

  4. UVA 11388 - GCD LCM 水~

    看题传送门 题目大意: 输入两个数G,L找出两个正整数a 和b,使得二者的最大公约数为G,最小公倍数为L,如果有多解,输出a<=b且a最小的解,无解则输出-1 思路: 方法一: 显然有G< ...

  5. Android应用性能优化系列视图篇——隐藏在资源图片中的内存杀手

    图片加载性能优化永远是Android领域中一个无法绕过的话题,经过数年的发展,涌现了很多成熟的图片加载开源库,比如Fresco.Picasso.UIL等等,使得图片加载不再是一个头疼的问题,并且大幅降 ...

  6. 如何设计一个基于mysql的消息系统

    https://segmentfault.com/a/1190000012255186

  7. 原生js螺旋运动

    window.onload=function(){ var oSpiral=document.getElementById('spiral'); var oUl=oSpiral.getElements ...

  8. HDU 1284 钱币兑换问题 母函数、DP

    题目链接:HDU 1284 钱币兑换问题 钱币兑换问题 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (J ...

  9. DATAGUARD在做SWITCHOVER切换时遇到问题总结

    1.主库在进行物理主备库角色转换的时候遇到ORA-01093错误 SQL> select switchover_status from v$database;   SWITCHOVER_STAT ...

  10. Android JNI编程(四)——C语言多级指针、数组取值、从控制台输入数组

    版权声明:本文出自阿钟的博客,转载请注明出处:http://blog.csdn.net/a_zhon/. 目录(?)[+] 一:前面我们介绍了一级指针的相关概念和用发,今天我们就来说一说多级指针. 1 ...