理解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
resolvePromise
is called with a valuey
, run[[Resolve]](promise, y)
. - If/when
rejectPromise
is called with a reasonr
, rejectpromise
withr
. - If both
resolvePromise
andrejectPromise
are 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的小伙伴们,是时候承认了,关于 ...
随机推荐
- MySQL高可用架构之MySQL5.7.19 PXC
CentOS7.3下Percona-XtraDB-Cluster-5.7.19集群部署PXC三节点安装:node1:10.10.10.11 node2:10.10.10.12node3:10.10.1 ...
- p5437 【XR-2】约定
分析 https://www.cnblogs.com/cjyyb/p/11111404.html 代码 #include<bits/stdc++.h> using namespace st ...
- 如何吸引用户打开自己发送的EDM邮件
一般来说,邮件发送到用户的收件箱,但用户不一定会阅读.因为每个用户收到的邮件都很多.那么,究竟应该如何吸引读者打开自己的EDM邮件呢? 只有当用户认识并信任发件人的时候,此时邮件的打开率是最高的,可以 ...
- 如何实现免登陆功能(cookie session?)
Cookie的机制 Cookie是浏览器(User Agent)访问一些网站后,这些网站存放在客户端的一组数据,用于使网站等跟踪用户,实现用户自定义功能. Cookie的Domain和Path属性标识 ...
- springmvc+ehcache简单例子
这里采用的是spring3.2.ehcache2.7.tomcat7.0(必须) 1.web.xml <?xml version="1.0" encoding="U ...
- 测开之路八十九:HTML之图片处理
<!--width.height设置图片尺寸 alt:当图片不能展示时,显示的内容 title:鼠标放上去时展示的内容--> <img src="../imges/img0 ...
- pthon之mock应用
研发过程中常见分工合作开发接口,但互相之间接口有依赖,这时候便可以使用mock 目录 1.安装 2.使用mock调试自己写的方法 3.使用mock解除依赖关系 1.安装 由于我的是python2.7, ...
- 用Python处理字幕文件
始 下了部老电影,找到了相关的中英文字幕,奇怪的是,英文字幕能正常现实,中文字幕却不可以,我一度以为是Linux下播放器编码的问题,但是怎么更改设置都无效,而我以前在看其他电影时,中文字幕是正常的.所 ...
- How are you to imagine anything if the images are always provided for you?
perdestrian: n. 行人 compliment: n. 赞扬 simply: adv. 只是,仅仅 shorten: vt. 缩短 accustom: vt. 习惯 collide: v. ...
- rac节点挂掉后,vip飘到别的节点,但是业务连接不上报 no listener问题处理
客户一套rac系统,三节点,其中一个节点的p260主机主板有问题(经常机器重启,好像是这个型号的通病,主板被炒到20W),临时把故障节点的vip作为业务地址用. 首先,查看确定故障节点vip飘到那个节 ...