理解Promise (4)
then 方法必须 返回一个新的promise

promise2 = promise1.then(onFulfilled, onRejected);
新的Promise 必须返回传递两个方法 onFulfilled, onRejected
If either onFulfilled or onRejected returns a value x, run the Promise Resolution Procedure [[Resolve]](promise2, x).
onFulfilled, onRejected 其中的某个都要返回 一个value
if either onFulfilled or onRejected returns a value x, run the Promise Resolution Procedure [[Resolve]](promise2, x)
如果onfulled或onrejected返回值x,请运行承诺解决过程[[解决]](promise2,x)。
let x = onfulfilled(this.value);
// x是普通值还是promise 如果是普通值 直接调用promise2的resolve
// 如果是promise 那应该让x这个promise执行 x.then
resolvePromise(promise2,x,resolve,reject);
这段代码是 resolvePromise 承诺解决过程
resolvePromise 这个函数里面 有Promise 这个参数,所以我们要拿到这个值 但是我们直接打印出来这个值 是 underfind 所以我们要用 promise2
这样,我们做到这里的时候 then 方法的大概结构就出来了
then(onfulfilled,onrejected){
let promise2;
promise2 = new Promise((resolve,reject)=>{
if(this.status === 'fulfilled'){
setTimeout(()=>{
try{
let x = onfulfilled(this.value);
// x是普通值还是promise 如果是普通值 直接调用promise2的resolve
// 如果是promise 那应该让x这个promise执行 x.then
resolvePromise(promise2,x,resolve,reject);
}catch(e){
reject(e);
}
},);
}
if(this.status === 'rejected'){
setTimeout(()=>{
try{
let x = onrejected(this.reason);
resolvePromise(promise2,x,resolve,reject);
}catch(e){
reject(e);
}
},)
}
if(this.status === 'pending'){
this.resolveCallbacks.push(()=>{
setTimeout(()=>{
try{
let x = onfulfilled(this.value);
resolvePromise(promise2,x,resolve,reject);
}catch(e){
reject(e);
}
},)
});
this.rejectCallbacks.push(()=>{
setTimeout(()=>{
try{
let x = onrejected(this.reason);
resolvePromise(promise2,x,resolve,reject);
}catch(e){
reject(e);
}
},)
})
}
});
return promise2
}
接下来我们来处理 The Promise Resolution Procedure 的问题
If promise and x refer to the same object, reject promise with a TypeError as the reason.
let resolvePromise = (promise2,x,resolve,reject) => {
if(promise2 === x){
return reject(new TypeError('循环引用'))
}
}
if x is an object or function,
if(typeof x === 'function' || (typeof x === 'object' && x !== null)){
}
Let then be x.then
let then = x.then; // 如果取then方法出错 那就用错误拒绝promise2
- f/when
resolvePromiseis called with a valuey, run[[Resolve]](promise, y). - If/when
rejectPromiseis called with a reasonr, rejectpromisewithr. - If both
resolvePromiseandrejectPromiseare called, or multiple calls to the same argument are made, the first call takes precedence, and any further calls are ignored.
if(typeof then === 'function'){ // 我就认为他是一个promise
then.call(x,y=>{ // 让当前的promise执行 ,不用多次取then方法了
// y 有可能还是一个promise , 继续调用resolvePromise方法,直到解析出一个常量为止,最终把常量传递下去
if(called) return; // 放置此方法多次被调用
called = true;
resolvePromise(promise2,y,resolve,reject);
},r=>{
if(called) return;
called = true;
reject(r); // 让当前的promise变成失败态即可
})
}else{
// x就是一个普通的对象 并没有then方法
resolve(x);
}
全部的代码:
let resolvePromise = (promise2,x,resolve,reject) => {
// 判断x的类型 来处理promise2是成功还是失败
// 所有的promise都遵循这个规范,不同的人写的promise可能会混用
// 尽可能考虑的周全 要考虑别人promise可能出错的情况
if(promise2 === x){
return reject(new TypeError('循环引用'))
}
// 判断x是不是一个promise ,这个x 可能不是自己的promise 所以为了安全 需要在进行校验,放置调一起用成功和失败
if(typeof x === 'function' || (typeof x === 'object' && x !== null)){
// 尝试取当前x的then方法, 这个then方法可能别人定义的时候 用的Object.defineProperty
let called;
try{
let then = x.then; // 如果取then方法出错 那就用错误拒绝promise2
if(typeof then === 'function'){ // 我就认为他是一个promise
then.call(x,y=>{ // 让当前的promise执行 ,不用多次取then方法了
// y 有可能还是一个promise , 继续调用resolvePromise方法,直到解析出一个常量为止,最终把常量传递下去
if(called) return; // 放置此方法多次被调用
called = true;
resolvePromise(promise2,y,resolve,reject);
},r=>{
if(called) return;
called = true;
reject(r); // 让当前的promise变成失败态即可
})
}else{
// x就是一个普通的对象 并没有then方法
resolve(x);
}
}catch(e){
if(called) return;
called = true;
reject(e);
}
}else{
// x肯定一个常量
resolve(x);
}
}
class Promise{
constructor(executor){
this.status = 'pending';
this.value;
this.reason;
this.resolveCallbacks = []; // 当then是pending 我希望吧成功的方法都放到数组中
this.rejectCallbacks = [];
let resolve = (value)=>{
if(this.status == 'pending'){
this.status = 'fulfilled';
this.value = value;
this.resolveCallbacks.forEach(fn=>fn()); // 发布
}
}
let reject = (reason)=>{
if(this.status === 'pending'){
this.status = 'rejected';
this.reason = reason;
this.rejectCallbacks.forEach(fn=>fn())
}
}
try{
executor(resolve,reject);
}catch(e){
reject(e);
}
}
then(onfulfilled,onrejected){
let promise2;
promise2 = new Promise((resolve,reject)=>{
if(this.status === 'fulfilled'){
setTimeout(()=>{
try{
let x = onfulfilled(this.value);
// x是普通值还是promise 如果是普通值 直接调用promise2的resolve
// 如果是promise 那应该让x这个promise执行 x.then
resolvePromise(promise2,x,resolve,reject);
}catch(e){
reject(e);
}
},);
}
if(this.status === 'rejected'){
setTimeout(()=>{
try{
let x = onrejected(this.reason);
resolvePromise(promise2,x,resolve,reject);
}catch(e){
reject(e);
}
},)
}
if(this.status === 'pending'){
this.resolveCallbacks.push(()=>{
setTimeout(()=>{
try{
let x = onfulfilled(this.value);
resolvePromise(promise2,x,resolve,reject);
}catch(e){
reject(e);
}
},)
});
this.rejectCallbacks.push(()=>{
setTimeout(()=>{
try{
let x = onrejected(this.reason);
resolvePromise(promise2,x,resolve,reject);
}catch(e){
reject(e);
}
},)
})
}
});
return promise2
}
}
module.exports = Promise;
理解Promise (4)的更多相关文章
- 大白话讲解Promise(二)理解Promise规范
上一篇我们讲解了ES6中Promise的用法,但是知道了用法还远远不够,作为一名专业的前端工程师,还必须通晓原理.所以,为了补全我们关于Promise的知识树,有必要理解Promise/A+规范,理解 ...
- 彻底理解Promise对象——用es5语法实现一个自己的Promise(上篇)
本文同步自我的个人博客: http://mly-zju.github.io/ 众所周知javascript语言的一大特色就是异步,这既是它的优点,同时在某些情况下也带来了一些的问题.最大的问题之一,就 ...
- 理解Promise的三种姿势
译者按: 对于Promise,也许你会用了,却并不理解:也许你理解了,却只可意会不可言传.这篇博客将从3个简单的视角理解Promise,应该对你有所帮助. 原文: Three ways of unde ...
- 理解Promise的3种姿势
译者按: 对于Promise,也许你会用了,却并不理解:也许你理解了,却只可意会不可言传.这篇博客将从3个简单的视角理解Promise,应该对你有所帮助. 原文: Three ways of unde ...
- 分步理解 Promise 的实现
一个 Promise 的运用: var firstPromise = new Promise(function(resolve,reject){ setTimeout(function(){ var ...
- 理解promise 02
1:promise是什么? 就是(链式)包装的回调函数. 2:语法 new Promise( function(resolve, reject) {...} /* executor */ ); exe ...
- 160701、理解 Promise 的工作原理
Javascript 采用回调函数(callback)来处理异步编程.从同步编程到异步回调编程有一个适应的过程,但是如果出现多层回调嵌套,也就是我们常说的厄运的回调金字塔(Pyramid of Doo ...
- 160623、理解 Promise 的工作原理
Javascript 采用回调函数(callback)来处理异步编程.从同步编程到异步回调编程有一个适应的过程,但是如果出现多层回调嵌套,也就是我们常说的厄运的回调金字塔(Pyramid of Doo ...
- 理解Promise简单实现的背后原理
在写javascript时我们往往离不开异步操作,过去我们往往通过回调函数多层嵌套来解决后一个异步操作依赖前一个异步操作,然后为了解决回调地域的痛点,出现了一些解决方案比如事件订阅/发布的.事件监听的 ...
- 理解promise 01
原文地址: http://pouchdb.com/2015/05/18/we-have-a-problem-with-promises.html 用Javascript的小伙伴们,是时候承认了,关于 ...
随机推荐
- MVP 实战
那么我们下面就要将这个类中的代码改写为 MVP 的写法,回顾上面提及的 MVP 架构的思想,它是将 View 层与 Model 层彻底隔离,意味着 View 和 Model 都不再持对方的引用,它们通 ...
- Java语言支持的变量类型有哪几种
Java语言支持的变量类型有: 类变量:独立于方法之外的变量,用 static 修饰. 实例变量:独立于方法之外的变量,不过没有 static 修饰. 局部变量:类的方法中的变量. 实例: publi ...
- ELK实时日志分析平台环境部署--完整记录(ElasticSearch+Logstash+Kibana )
https://blog.csdn.net/oLevin/article/details/81020794
- 用Python给头像加上圣诞帽或圣诞老人小图标
随着圣诞的到来,想给给自己的头像加上一顶圣诞帽.如果不是头像,就加一个圣诞老人陪伴. 用Python给头像加上圣诞帽,看了下大概也都是来自2017年大神的文章:https://zhuanlan.z ...
- UVALive 7325 Book Borders
题目链接:https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_ ...
- xpath 算法
w https://www.w3.org/TR/xpath20/ Before an expression can be processed, its input data must be repre ...
- 内存地址 Memory Management
Memory Management https://docs.python.org/2/c-api/memory.html Memory management in Python involves a ...
- Java 位运算超全面总结
1.原码.反码.补码 关于原码.反码.补码的相关知识作者不打算在这里长篇大论,相关知识已有别的大佬总结很好了,还请老铁自行 Google,不过有篇知乎回答是作者学编程以来见过对相关知识最通俗易懂,生动 ...
- RocketMQ 创建和删除 topic,以及 broker 和 nameserver 之间的心跳
命令行主类:org.apache.rocketmq.tools.command.MQAdminStartup 客户端创建 topic 程序参数:updateTopic -n localhost:987 ...
- lua-resty-kafka erro xxxx could not be resolved (3: Host not found)
问题:使用 lua-resty-kafka 向 kafka 发送数据失败,报错如下: slave6 could not be resolved (: Host not found) 配置信息: lua ...