原生JS实现Promi(详解)

更新时间:2023-06-09 10:01:47 阅读: 评论:0

原⽣JS 实现Promi (详解)
摘要
⾸先呢,Promi是异步中⽐较重要的知识点,学习的最好⽅法就是掌握它的基本原理。
所以这⼀篇主要说⼀下如何⽤JS来实现⼀个⾃⼰的promi。
构造函数
⾸先我们来看⼀下我们是如何使⽤promi的,我们在实例化对象是这么使⽤的:
所以我们在创建我们⾃⼰的类要考虑到如何使⽤这个参数。
西班牙语 我爱你我们来看⼀下, new Promi 的时候传了⼀个回调函数,在这个回调函数中的代码应该是被⽴即执⾏的。
⽽在这个回调函数中,还带有这两个参数resolve和reject(也是回调函数)。
所以在我们的构造函数中,应该是有这两个函数resolve和reject(暂时先不管这两个函数是做什么的)。
我们知道promi是有三个属性的:
pending : 待定 fulfilled : 对应resolve函数 rejected : 对应reject函数
并且状态⼀旦改变就不能再更改了。
所以我们的构造函数之中应该有表⽰当前promi状态的属性。
我们知道不管使⽤resolve还是reject都会传⼊⼀个res变量,作为结果值,所以我们在⽤⼀个属性来保存resolve和reject的结果值。最后我们可以设计出这样的构造函数:
then 和 catch ⽅法
我们先来回顾⼀哈怎么使⽤这两个⽅法:    let  p1 = new  Promi ((resolve , reject ) => {      let  random = Math .floor (Math .random () * 10);      if  (random > 4) {        resolve ('sucess')      } el  {        reject ('erro')      }    })
1
2
3
4
5
ladyandgentleman
6
7
8function  Mypromi  (config ) {  this .status = 'pending';  this .res = ''  let  resolve  = (data ) => {    this .status = 'fulfilled';    this .res = data  }  let  reject  = (data ) => {    this .status = 'rejected';    this .res = data  }  config (resolve , reject )}
1
2
3
4
5
6
7
8
9
10
分享阅读11
12
13
14
上⾯的代码我们可以看到,then和catch⽅法,都接受了⼀个回调函数
⽽这个回调函数的参数也就是我们之前定义的s。
所以我们可以想到这么做:
但是这种⽅法不能实现链式调⽤,就是不能连着使⽤then⽅法。 但是如果我想实现出这个模式,我们应该在then⽅法下回⼀个对象,⽽这个对象正常来讲就是this。 所以我们可以直接返回this吗,看下⾯这个情况。
在then⽅法下如果返回了⼀个新的promi的话,我们就不能直接在then⽅法⾥⾯直接返回this了。
所以我们应该先判断then的回调函数是否返回了新的对象,如果没有才返回当前then的this对象。    p1      .then (res => {        console .log (res );      })      .then (res => {        console .log (res );      })      .catch (err => {        console .log (err );      })
1
2
3
4
5
6
7
8
9
10Mypromi .prototype .then  = function  (config ) {  if  (this .status == 'fulfilled') {    config (this .res )  }}Mypromi .prototype .catch  = function  (config ) {  if  (this .status == 'rejected') {    config (this .res )  }}
修改病句类型1
2
3
4
5
6
7
8
910
11p1  .then (res => {    console .log (res );    return  new  Promi ((resolve , reject ) => {      resolve ('1111')    })  })  .then (res => {    console .log (res );  })  .catch (err => {    console .log (err );  })
1
2
3
4
5
埃及总统穆巴拉克
6
7
8
9
10
11
12
13Mypromi .prototype .then  = function  (config ) {  if  (this .status == 'fulfilled') {    var  res = config (this .res )  }  return  res || this ;}Mypromi .prototype .catch  = function  (config ) {  if  (this .status == 'rejected') {    var  res = config (this .res )  }  return  res || this ;}
1
2
3
4
5
6
7
8
9
10
11
12
13
解决异步问题
上⾯的代码,似乎看着没有什么问题了,但是如果我这么写的话:
问题就⼤⼤的出来了,为什么呢? 因为我在p2.then的时候,定时器没有跑完,所以p2的状态现在还是pending,根本不会⾛下去。这⾥⾯我们⽤⼀种经典的解决模式,在我写之前的axios和路由也经常可以看到。
在then⽅法中,如果当前状态为pending(这句话很重要o),我们就把当前的回调函数保存下来(不⼀定是⼀个,有可能是多个then,所以我们采⽤数组保存)。
那我们保存起来什么时候⽤呢?当然是在定时器结束后⽤!那定时器什么时候结束呢?当然是当前promi状态改变的时候,所以,我们在resolve和reject⽅法之中,要将这些⽅法进⾏调⽤
所以我们要修改构造函数:
然后再修改我们的then和catch⽅法:    let  p2 = new  Mypromi ((resolve , reject ) => {      tTimeout (() => {        reject ('p2 resolve')      }, 1000);    })
1
2
3
4
5function  Mypromi  (config ) {  this .status = 'pending';  this .res = '';  this .saveResolve = [];  this .saveReject = [];  let  resolve  = (data ) => {    if  (this .status == 'pending') {      this .status = 'fulfilled';      this .res = data      this .saveResolve .forEach (val => {        val (this .res )      })    }  }  let  reject  = (data ) => {    if  (this .status == 'pending') {      this .status = 'rejected';      this .res = data      this .saveReject .forEach (val => {        val (this .res )      })    }  }  config (resolve , reject );}
1
2
3
4
5
6
7reception是什么意思
8
9
10
11
12
13
亚洲大学排名
14
15
16
17
18
19
20
21
22
23
24
25
这样关于异步的问题我们就解决了。
all 和race ⽅法
还是⽼样⼦,在写之前我们先回顾⼀下是怎么⽤的:
那我们知道,⼆者都死以⼀个数组作为参数,这⾥⾯我门就不考虑其他的情况了,我就当数组⾥⾯全是promi对象了。。。
⼆者的区别在于:
all:当所有的promi都执⾏完,并且状态都为fulfilled,all⽅法返回的promi为fulfilled,否则为rejected。
race:第⼀个出现结果的promi对象就是race放回的promi的结果。
现在我们来想⼀下all⽅法如何来实现,我们拿到了数组参数之后,⼀定是要遍历⼀遍的。
然后对于每⼀个元素都调⽤then⽅法和catch⽅法。
then⽅法要有⼀个结果数组保存每个promi的结果值。
我们可以⽤⼀个计数器来计算then⽅法的调⽤次数,如果计数器的⼤⼩等于数组长度,那么就证明所有的promi全部都是fulfilled,可以返回结果数组。
catch⽅法只要是被调⽤了⼀次,那么直接返回结果,不多bb,直接返回
最后记住要把新的promi返回o。Mypromi .prototype .then  = function  (config ) {  if  (this .status == 'pending') {    this .saveResolve .push (config );  }  if  (this .status == 'fulfilled') {    var  res = config (this .res )  }  return  res || this ;}Mypromi .prototype .catch  = function  (config ) {  if  (this .status == 'pending') {    this .saveReject .push (config )  }  if  (this .status == 'rejected') {    var  res = config (this .res )  }  return  res || this ;}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19    Mypromi .all ([p2, p3, p4])      .then (res => {        console .log (res );      })      .catch (err => {        console .log (err );      })    Mypromi .race ([p2, p3, p4])      .then (res => {        console .log (res );      })      .catch (err => {        console .log (err );      })
1
2
3
fieldofview
4
5
6
7
8
9
10
11
12
13
14
15
race的⽅法的话,实现起来可能就更简单了,不管那个promi的then⽅法还是catch⽅法触发了,直接返回结果:Mypromi .all  = function  (arr ) {  let  result = [];  let  count = 0;  let  promi = new  Mypromi ((resolve , reject ) => {    for  (var  i = 0; i < arr .length ; i ++) {      arr [i ]        .then (res => {          result .push (res );          count ++;          if  (count == arr .length ) resolve (result );        })        .catch (err => {          reject (err )        })    }  })  return  promi }
1团支书英文
2
3
4
5
6
7
8
9
10
11
12education in china
13
14
15
16
17
18
19Mypromi .race  = function  (arr ) {  let  promi = new  Mypromi ((resolve , reject ) => {    for  (var  i = 0; i < arr .length ; i ++) {      arr [i ]        .then (res => {          resolve (res );        })        .catch (err => {          reject (err )        })    }  })  return  promi }1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

本文发布于:2023-06-09 10:01:47,感谢您对本站的认可!

本文链接:https://www.wtabcd.cn/fanwen/fan/90/139102.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:函数   回调   对象   结果
相关文章
留言与评论(共有 0 条评论)
   
验证码:
Copyright ©2019-2022 Comsenz Inc.Powered by © 专利检索| 网站地图