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

setTimeout(function() {
console.log(1)
}, 0);
new Promise(function executor(resolve) {
console.log(2);
for( var i=0 ; i<10000 ; i++ ) {
i == 9999 && resolve();
}
console.log(3);
}).then(function() {
console.log(4);
});
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.如何实现链式调用并且管理状态

首先是构造函数:

//全局宏定义
var PENDING = 0;
var FULFILLED = 1;
var REJECTED = 2;
//Promise构造函数
function Promise(fn){
var self = this;
self.state = PENDING;//初始化状态
self.value = null;//存储异步结果的对象变量
self.handlers = [];//存储回调函数,这里没保存失败回调函数,因为这是一个dome
//异步任务成功后处理,这不是回调函数
function fulfill(result){
if(self.state === PENDING){
self.state = FULFILLED;
self.value = result;
for(var i=0;i<self.handlers.length;i++){
self.handlers[i](result);
} }
} //异步任务失败后的处理,
function reject(err){
if(self.state === PENDING){
self.state = REJECTED;
self.value = err;
}
}
fn&&fn(fulfill,reject); };

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

回调函数方法then:

//使用then方法添加回调函数,把这次回调函数return的结果当做return的promise的resolve的参数
Promise.prototype.then = function(onResolved, onRejected){
var self = this;
return new Promise(function(resolve, reject){
var onResolvedFade = function(val){
var ret = onResolved?onResolved(val):val;//这一步主要是then方法中传入的成功回调函数通过return来进行链式传递结果参数
if(ret instanceof Promise){//回调函数返回值也是promise的时候
ret.then(function(val){
resolve(val);
});
}
else{
resolve(ret);
}
};
var onRejectedFade = function(val){
var ret = onRejected?onRejected(val):val;
reject(ret);
};
self.handlers.push(onResolvedFade);
if(self._status === FULFILLED){
onResolvedFade(self._value);
} if(self._status === REJECTED){
onRejectedFade(self._value);
}
});
}

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

测试代码:

function async(value){
var pms = new Promise(function(resolve, reject){
setTimeout(function(){
resolve(value);;
}, 1000);
});
return pms;
}
async(1).then(function(result){
console.log('the result is ',result);//the result is 2
return result;
}).then(function(result){
console.log(++result);//
});

 

探究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. MWPhotoBrowser 属性详解 和代理解释

    --------0.MWPhoto简单属性解释---------------- MWPhoto *photo = [MWPhoto photoWithURL:[NSURL URLWithString: ...

  2. 使用MongoDb连接数据库服务器

    链接MongoDb数据库服务器的字符串格式: mongodb://[username:password@]host1[:port1][,host2[:port2],...[,hostN[:portN] ...

  3. ITFriend网站内测公测感悟

    4月份做出网站Demo,就开始让用户使用了. 最初的黄色版界面,被吐槽得比较厉害. 关于界面,每个人都有自己的看法,只是喜欢和不喜欢的人比例不一样. 后来,花3400元请了个设计师,设计了一套界面,整 ...

  4. SpringBoot错误信息总结(不定时更新)

    1." java.lang.IllegalStateException: @Bean method ShiroConfig.cacheManager called as a bean ref ...

  5. Spring Boot系列二 Spring @Async异步线程池用法总结

    1. TaskExecutor Spring异步线程池的接口类,其实质是java.util.concurrent.Executor Spring 已经实现的异常线程池: 1. SimpleAsyncT ...

  6. jQuery实现多种切换效果的图片切换的五款插件

    1:Nivo SliderNivoslider:丰富的图片切换效果 官方网址:https://themeisle.com/plugins/nivo-slider 查看演示:https://www.he ...

  7. [Angular2 Form] patchValue, setValue and reset() for Form

    Learn how to update part of form model, full form model and reset whole form. We have form definetio ...

  8. php面试题二--解决网站大流量高并发方案(从url到硬盘来解决高并发方案总结)

    php面试题二--解决网站大流量高并发方案(从url到硬盘来解决高并发方案总结) 一.总结 从外到内解决网站大流量高并发问题---从提交一个url开始(从用户按下搜索栏回车键开始) url最开始会到d ...

  9. 读Effective Objective-C [提高OC代码质量总结笔记第一篇:熟悉OC]

    一.OC特性 OC 为 C 语言添加了面向对象特性,是其超集; OC 使用动态绑定的消息结构,也就是,在运行时才会检查对象类型; 接收一条消息后,究竟应执行何种代码,由运行期环境来决定,而非 编译器; ...

  10. C++中string类的操作函数。

    相信使用过MFC编程的朋友对CString这个类的印象应该非常深刻吧?的确,MFC中的CString类使用起来真的非常的方便好用.但是如果离开了MFC框架,还有没有这样使用起来非常方便的类呢?答案是肯 ...