前端可能是目前最易理解的手写promiseWord文档格式.docx

上传人:b****2 文档编号:417028 上传时间:2023-04-28 格式:DOCX 页数:20 大小:277.44KB
下载 相关 举报
前端可能是目前最易理解的手写promiseWord文档格式.docx_第1页
第1页 / 共20页
前端可能是目前最易理解的手写promiseWord文档格式.docx_第2页
第2页 / 共20页
前端可能是目前最易理解的手写promiseWord文档格式.docx_第3页
第3页 / 共20页
前端可能是目前最易理解的手写promiseWord文档格式.docx_第4页
第4页 / 共20页
前端可能是目前最易理解的手写promiseWord文档格式.docx_第5页
第5页 / 共20页
前端可能是目前最易理解的手写promiseWord文档格式.docx_第6页
第6页 / 共20页
前端可能是目前最易理解的手写promiseWord文档格式.docx_第7页
第7页 / 共20页
前端可能是目前最易理解的手写promiseWord文档格式.docx_第8页
第8页 / 共20页
前端可能是目前最易理解的手写promiseWord文档格式.docx_第9页
第9页 / 共20页
前端可能是目前最易理解的手写promiseWord文档格式.docx_第10页
第10页 / 共20页
前端可能是目前最易理解的手写promiseWord文档格式.docx_第11页
第11页 / 共20页
前端可能是目前最易理解的手写promiseWord文档格式.docx_第12页
第12页 / 共20页
前端可能是目前最易理解的手写promiseWord文档格式.docx_第13页
第13页 / 共20页
前端可能是目前最易理解的手写promiseWord文档格式.docx_第14页
第14页 / 共20页
前端可能是目前最易理解的手写promiseWord文档格式.docx_第15页
第15页 / 共20页
前端可能是目前最易理解的手写promiseWord文档格式.docx_第16页
第16页 / 共20页
前端可能是目前最易理解的手写promiseWord文档格式.docx_第17页
第17页 / 共20页
前端可能是目前最易理解的手写promiseWord文档格式.docx_第18页
第18页 / 共20页
前端可能是目前最易理解的手写promiseWord文档格式.docx_第19页
第19页 / 共20页
前端可能是目前最易理解的手写promiseWord文档格式.docx_第20页
第20页 / 共20页
亲,该文档总共20页,全部预览完了,如果喜欢就下载吧!
下载资源
资源描述

前端可能是目前最易理解的手写promiseWord文档格式.docx

《前端可能是目前最易理解的手写promiseWord文档格式.docx》由会员分享,可在线阅读,更多相关《前端可能是目前最易理解的手写promiseWord文档格式.docx(20页珍藏版)》请在冰点文库上搜索。

前端可能是目前最易理解的手写promiseWord文档格式.docx

let 

resolve 

() 

=>

};

失败

reject 

立即执行

executor(resolve, 

reject);

}

上面的代码实现了Promise构造函数的主体,但有两个问题:

2.executor有可能会出错,对吧,毕竟是用户传进来的方法,类似下面这样。

如果executor出错,报错我们需要用trycatch捕获一下,Promise应该被其throw出的值reject:

new 

Promise(function(resolve, 

reject) 

console.log(a) 

没有被定义

})

3.resolve、reject还是空函数,我们需要在里面补上逻辑。

接下来继续完善:

Promise(executor){

初始化state为等待态

value 

state改变,resolve调用就会失败

if 

(this.state 

=== 

) 

resolve调用后,state转化为成功态

fulfilled'

储存成功的值

value;

reason 

state改变,reject调用就会失败

reject调用后,state转化为失败态

rejected'

储存失败的原因

reason;

如果executor执行报错,直接执行reject

try{

catch 

(err) 

reject(err);

用一张图小结一下:

上面的代码不算特别复杂,下面的then方法有点复杂。

实现then方法

Promise对象有一个then方法,用来注册在这个Promise状态确定后的回调。

当Promise的状态发生了改变,不论是成功或是失败都会调用then方法

then方法使用方法如下:

then 

方法传入两个方法作为参数,一个是fn1方法,一个是 

方法

p1.then(function 

fn1(data){

方法的参数,用于获取promise对象的值

}, 

fn2(err){

方法的参数,用于获取失败的原因

从上面的例子,很明显,我们得出结论:

2.then方法可以在p1实例上调用。

因此then方法的实现是在Promise的prototype上。

3.then方法会返回一个Promise,而且是返回一个新的Promise(详情)对象。

4.可以多次调用then方法,也就是链式调用,并且每次会返回一个新Promise对象,Promise状态是不确定的,可能是fullfilled,也可能是resolve,取决于那一次调用then时,fn1的返回值。

所以,then方法的实现也很简单,根据Promise状态来调用不同的回调函数即可

下面是then方法的思路图:

下面我们来实现then方法:

then方法接收两个参数,fn1,fn2,分别为Promise成功或失败后的回调

Promise.prototype.then 

function(fn1, 

fn2) 

var 

self 

this

promise2

首先对入参 

fn1, 

fn2做判断

typeof 

function'

?

:

function(v) 

{}

function(r) 

(self.status 

resolved'

return 

promise2 

//todo

todo

首先,对入参fn1,fn2做判断。

规范中说,fn1和fn2都是可选参数。

也就是说可以传也可以不传。

传入的回调函数也不是一个函数类型,那怎么办?

规范中说忽略它就好了。

因此需要判断一下回调函数的类型,如果明确是个函数再执行它。

其次,Promise总共有三种可能的状态,我们分三个if块来处理,在里面分别都返回一个newPromise。

所以,接下来的逻辑是:

∙如果promise状态是resolved,需要执行fn1;

∙如果promise状态是rejected,需要执行fn2;

∙如果promise状态是pending,我们并不能确定调用fn1还是fn2,只能先把方法都保存在fn1Callback,fn2Callback数组中。

等到Promise的状态确定后再处理。

根据上面的逻辑,填充下面代码:

把 

fn1、fn2 

放在 

try 

里面,毕竟 

是用户传入的,报错嘛,很常见

fn1(self.data)

执行后,会有返回值,通过 

注入到 

返回的 

promise 

resolve(x)

(e) 

reject(e) 

fn2(self.data)

reject(x)

reject(e)

this.fn1Callback.push(function(value){

fn1(self.data);

this.fn2Callback.push(function(value) 

fn2(self.data);

∙fn1,fn2都是用户传入的,有可能报错唉,所以要放在trycatch里面

∙fn1,fn2的返回值,我们记为x,规范中的命名也是x,保持一致。

x值将在下文中频繁使用。

then函数本质是把fn1的返回值,包装成一个promise返回出去。

问题是,fn1的返回值是开发者写的,可能千奇百怪。

上面代码中,假定x是一个普通值。

其实实际上,x有不同的情况,我们得去分别处理:

∙如果x是一个普通值,如同上面的代码,直接使用resolve方法,then就可以返回一个正常的promise

Promise((resolve) 

∙如果x是一个promise,需要等待这个promise状态变化,拿到fullfilled的值。

然后我们代码再改一改,增加一个判断

(x 

instanceof 

Promise) 

x.then((data) 

{resolve(data)}, 

{reject(e)})

else 

∙根据规定,我们需要兼容各种百花齐放的写法,比如说,如果x是一个对象,并且对象有then方法,也就是所谓的thenable对象,则我们得这样处理:

(typeof 

x.then 

){

x.then(function(y){

resolve(y)

function(e){

}) 

上面,我们新增了一些逻辑,为了处理x返回值的各种情况。

我们需要把这些逻辑,挪到一个resolvePromise方法中,resolvePromise负责把各种稀奇古怪的x包装成一个正常的promise。

resolvePromise

resolvePromise方法,就是为了把x包裹成一个正常的promise

resolvePromise(promise2, 

x, 

resolve, 

为了防止循环引用

(promise2 

x) 

reject(new 

TypeError('

Chaining 

cycle 

detected 

for 

promise!

));

如果 

是 

promise

x.then(function 

(data) 

resolve(data)

});

return;

object 

类型或者是 

function

((x 

!

== 

null) 

&

((typeof 

object'

|| 

))) 

拿x.then可能会报错

先拿到 

x.then

x.then;

called

这里的写法,是 

then.call(this, 

fn2)

then.call(x, 

(y) 

//called是干什么用的呢?

有一些 

实现的不是很规范,瞎搞的,比如说,fn1, 

本应执行一个,

但是有些then实现里面,fn1, 

fn2都会执行

为了 

和 

只能调用一个, 

设置一个 

called 

标志位

(called) 

true;

y, 

(r) 

reject(r);

resolve(x);

reject(e);

上面代码,需要注意的地方:

∙varthen=x.then这一行代码可能会报错,需要用trycatch包一下。

为什么取对象上的属性有报错的可能?

Promise有很多实现(bluebird,Q等),Promises/A+只是一个规范,大家都按此规范来实现Promise才有可能通用,因此所有出错的可能都要考虑到,假设另一个人实现的Promise对象使用Object.defineProperty()恶意的在取值时抛错,我们可以防止代码出现Bug。

∙如果对象中有then,且then是函数类型,就可以认为是一个Promise对象,之后,使用x作为this来调用then方法。

∙如果x===promise2,则是会造成循环引用,自己等待自己完成,则报“循环引用”错误。

x和promise2是同一个是什么情况呢?

p2 

p1.then(function(data){

console.log(data)

p2;

上面的例子中,p1.then()的返回值是p2,fn1的返回值也是p2。

这会存在什么问题呢?

promise如果不手动的调用resolve方法,是没有办法修改状态的。

p2的状态没法改变,没法自己改动自己的状态,永远不会被fullfilled、rejected

∙我们需要不同的Promise实现能够相互交互,即我们要把fn1/fn2的返回值,x,当成一个可能是Promise的对象,也即标准里所说的thenable,并以最保险的方式调用x上的then方法。

如果大家都按照标准实现,那么不同的Promise之间就可以交互了。

而标准为了保险起见,即使x返回了一个带有then属性但并不遵循Promise标准的对象(比如说这个x把它then里的两个参数都调用了,同步或者异步调用(PS,原则上then的两个参数需要异步调用,下文会讲到),或者是出错后又调用了它们,或者then根本不是一个函数),也能尽可能正确处理。

then里面的函数需要异步执行

最后,我们刚刚说到,原则上,promise.then(onResolved,onRejected)里的这两相函数需要异步调用,关于这一点,标准里也有说明:

Inpractice,thisrequirementensuresthatonFulfilledandonRejectedexecuteasynchronously,aftertheeventloopturninwhichtheniscalled,andwithafreshstack.

那么如何将同步代码变成异步执行呢?

可以使用setTimeout函数来模拟一下:

setTimeout(()=>

//此入的代码会异步执行

},0);

利用此技巧,将代码then执行处的所有地方使用setTimeout变为异步即可,举个栗子:

setTimeout(() 

fn1(value);

promise主体结构

1. 

定义 

status 

状态

2. 

的数组

3. 

4. 

executor 

执行

this;

self.status 

self.fn1Callback 

self.fn2Callback 

做到事情

修改this 

实例的状态

这里的data

遍历执行 

this 

fn1Callback 

上挂载的方法

resolve(value) 

(value 

value.then(resolve, 

异步执行所有的回调函数

self.data 

(let 

0;

<

self.fn1Callback.length;

i++) 

self.fn1Callback[i](value);

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 法律文书 > 调解书

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2