理解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的小伙伴们,是时候承认了,关于 ...
随机推荐
- xargs -i参数详解
学习所需,文章转载过来! xargs与find经常结合来进行文件操作,平时删日志的时候只是习惯的去删除,比如 # find . -type f -name "*.log" | xa ...
- EDM营销必知:电子邮件打开和点击的几组数据
在EDM营销中,了解一下电子邮件何时被打开和点击很重要.这有助于我们在合适的时间发送邮件出去,从而带来最大化的效果. 1.邮件打开的最高峰在早上8点至9点之间,其次是下午三点到四点.因此,在这个时间发 ...
- Vue知识整理6:JavaScript表达式
可在vue中运用js表达式,完成数据的运算(包括三元运算).比较等操作.
- beanstalkd 安装和配置
安装 安装以centos为例 yum install beanstalkd 配置 使用centos yum安装,通过查看服务脚本发现有这个配置文件 cat /etc/sysconfig/beansta ...
- 3 hadoop安装Standalone模式和伪分布式模式
1 Standalone模式默认模式,即默认配置即是standalone模式装好hadoop-client,会将依赖的包安装好yum install hadoop-client配置文件各个配置文件在/ ...
- js-禁止长页面滚动
标题的需求问题其实我经常遇到.尤其是在碰到页面同时出现有视频及弹层的情况. 当然我说的问题皆是针对微信H5开发的哈 IOS中,视频播放,弹层出现时,视频在弹层的下面,不会出现问题: 安卓手机中,完了, ...
- 剑指offer(1):数组
1 写作计划 最近在看<剑指offer>,发现自己有很多的数据结构与算法的基础知识要复习,<好书一起读(131):让写作更好>中提到用写作倒逼阅读,我很是赞同.所以,计划以&l ...
- mssql 堆叠注入
添加用户 exec master.dbo.xp_cmdshell 'net user leeww 123456 /add' 提升权限 exec master.dbo.xp_cmdshell 'net ...
- 安全运维 - Windows系统攻击回溯
Windows应急事件 病毒.木马.蠕虫 Web服务器入侵事件或第三方服务入侵事件 系统入侵事件 网络攻击事件(DDOS.ARP.DNS劫持等) 通用排查思路 获知异常事件基本情况 发现主机异常现象的 ...
- 从建立yum仓库到搭建ftp以及http服务
1 什么是yum仓库 yum工作需要依赖C/S架构工作模式的文件服务器,服务器中存放了yum工作时所需的程序包.yum接收到需要安装的程序包的名称之后,通过文件共享协议(或者文件传输协议),在配置文件 ...