1.首先申明Promise , promise 是一个类,接收一个函数作为参数,函数中会接收两个参数,一个是成功的回调 resolve,一个是失败的回调 reject, 在new 该类的的时候,传入的函数会立即执行

 1 class Promise {
 2   constructor(task){
 3     let resolve = () => {
 4 
 5     }
 6     let reject = () => {
 7 
 8     }
 9     task(resolve,reject)
10   }
11 }

2.解决基本状态,promise有三个状态  pending, fulfilled, rejected

pending为初始态,可以转为 fulfilled 成功态   也可以转为 rejected 失败态

fulfilled 成功态  不可以转为其他状态  并且有一个返回值 value

rejected 失败态  不可以转为其他状态 并且有一个错误返回值  reason

如果任务函数报错 直接执行 reject

 1 class Promise2 {
 2   constructor(task){
 3     this.status = 'pending'
 4     this.value = undefined
 5     this.reason = undefined
 6     let resolve = value => {
 7       if(this.status === 'pending'){
 8         this.status = 'fulfilled'
 9         this.value = value
10       }
11     }
12     let reject = reason => {
13       if(this.status === 'pending'){
14         this.status = 'rejected'
15         this.reason = reason
16       }
17     }
18     try{
19       task(resolve,reject)
20     }catch(err){
21       reject(err)
22     }
23   }
24 }

3.then方法

在promise 中有个then 的方法,里面有两个参数 onFulfilled,onRejected,成功有成功的值  失败有失败的原因

当状态值是 fulfilled 的时候 执行 onFulfilled 函数并传入 this.value .当状态值是rejected 的时候 执行onRejected 函数并且传入this.reason

如果 onFulfilled onRejected 是函数,必须在 fulfilled 和 rejected 后调用  并且第一个参数 分别是 this.value 和 this.reason

 1 class Promise2 {
 2   constructor(task){
 3     this.status = 'pending'
 4     this.value = undefined
 5     this.reason = undefined
 6     let resolve = value => {
 7       if(this.status === 'pending'){
 8         this.status = 'fulfilled'
 9         this.value = value
10       }
11     }
12     let reject = reason => {
13       if(this.status === 'pending'){
14         this.status = 'rejected'
15         this.reason = reason
16       }
17     }
18     try{
19       task(resolve,reject)
20     }catch(err){
21       reject(err)
22     }
23   }
24   then(onFulfilled,onRejected){
25     if(this.status === 'fulfilled'){
26       onFulfilled(this.value)
27     }
28     if(this.status === 'rejected'){
29       onRejected(this.reason)
30     }
31   }
32 }

4.解决异步的问题

上面基本可以解决一些同步的代码,但是当resolve 在setTimeout 中执行的时候,then 的时候的status 还是pending 状态,那么我们需要在then 的时候将成功和失败的函数存起来,在resolve 或者reject 的时候去调用

类似于发布订阅模式 先将函数存在起来  而且可能会有多个then 函数 所有将成功和失败的函数分别存在 两个数组中 成功或者失败的时候用forEach 去调用

 1 class Promise2 {
 2   constructor(task){
 3     this.status = 'pending'
 4     this.value = undefined
 5     this.reason = undefined
 6     // 成功的回调函数存放数组
 7     this.onFulfilledCallbacks = []
 8     // 失败的函数回调存放数组
 9     this.onRejectedCallbacks = [] 
10     let resolve = value => {
11       if(this.status === 'pending'){
12         this.status = 'fulfilled'
13         this.value = value;
14         // resolve 执行后调用成功回调函数
15         this.onFulfilledCallbacks.forEach(fn => fn())
16       }
17     }
18     let reject = reason => {
19       if(this.status === 'pending'){
20         this.status = 'rejected'
21         this.reason = reason
22         // reject 执行后调用失败回调函数
23         this.onRejectedCallbacks.forEach(fn => fn())
24       }
25     }
26     try{
27       task(resolve,reject)
28     }catch(err){
29       reject(err)
30     }
31   }
32   then(onFulfilled,onRejected){
33     if(this.status === 'fulfilled'){
34       onFulfilled(this.value)
35     }
36     if(this.status === 'rejected'){
37       onRejected(this.reason)
38     }
39     if (this.status === 'pending'){
40       this.onFulfilledCallbacks.push(onFulfilled(this.value))
41       this.onRejectedCallbacks.push(onRejected(this.reason))
42     }
43   }
44 }

5.解决链式调用的问题

我们常常这样用  new Promise().then().then() 来解决回调地狱的问题

1.为了达成链式调用 在then 函数中返回 一个新的promise,我们这叫 promise2  = new Promise(function(resolve,reject){})

2.将promise2 中的返回值传递给后面的then方法

3.如果返回的是一个普通值 也传递给后面的then 方法中

4.按规范 onFulfilled() 或者 onRejected()即第一个then 的返回值 我们叫 x ,判断x 的函数我们叫 resolvePromise

 在resolvePromise 中首先要看x 是不是Promise

如果是Promise 就取他的结果 作为新的promise2 的成功的结果

如果是成功的值 直接作为promise2 的成功的结果

resolevePromise 的参数有 promise2 这个是默认返回的promise  x 是我们自己返回的对象  还要 resolve,reject  是promise2 的

 1 class Promise2 {
 2   constructor(task){
 3     this.status = 'pending'
 4     this.value = undefined
 5     this.reason = undefined
 6     // 成功的回调函数存放数组
 7     this.onFulfilledCallbacks = []
 8     // 失败的函数回调存放数组
 9     this.onRejectedCallbacks = [] 
10     let resolve = value => {
11       if(this.status === 'pending'){
12         this.status = 'fulfilled'
13         this.value = value;
14         // resolve 执行后调用成功回调函数
15         this.onFulfilledCallbacks.forEach(fn => fn())
16       }
17     }
18     let reject = reason => {
19       if(this.status === 'pending'){
20         this.status = 'rejected'
21         this.reason = reason
22         // reject 执行后调用失败回调函数
23         this.onRejectedCallbacks.forEach(fn => fn())
24       }
25     }
26     try{
27       task(resolve,reject)
28     }catch(err){
29       reject(err)
30     }
31   }
32   then(onFulfilled,onRejected){
33     let promise2 = new Promise2((resolve,reject) =>{
34       if(this.status === 'fulfilled'){
35         let x = onFulfilled(this.value)
36         resolvePromise(promise2,x,resolve,reject)
37       }
38       if(this.status === 'rejected'){
39        let x = onRejected(this.reason)
40        resolvePromise(promise2,x,resolve,reject)
41       }
42       if (this.status === 'pending'){
43         this.onFulfilledCallbacks.push(() =>{
44           let x = onFulfilled(this.value)
45           resolvePromise(promise2,x,resolve,reject)
46         })
47         this.onRejectedCallbacks.push(() => {
48           let x = onRejected(this.reason)
49           resolvePromise(promise2,x,resolve,reject)
50         })
51       }
52     })
53     return promise2
54     
55   }
56 }

6.我们在来完成 resolvePromise 函数

让不同的promise代码互相套用,叫做resolvePromise

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

比如

1 let p = new Promsie((resolve) => {
2    resolve(0) 
3 })
4 let p2 = p.then(data => {
5   return p2       
6 )

先判断x

如果   if x is an object or function,Let then be x.then

x不能是 null 

x是普通值 直接 resolve(x)

x是对象或者函数的时候  let then = x.then

如果取then 报错  直接走 reject()

如果then是个函数,则用call执行then,第一个参数是this,后面是成功的回调和失败的回调

如果成功的回调还是pormise,就递归继续解析

成功和失败只能调用一个 所以设定一个called来防止多次调用

 

function resolvePromise(promise2, x, resolve, reject){ 
    // 循环引用报错  
     if(x === promise2){     
       // reject报错   
         return reject(new TypeError('Chaining cycle detected for promise'));  
     }  
       // 防止多次调用 
    let called;   // x不是null 且x是对象或者函数 
    if (x != null && (typeof x === 'object' || typeof x === 'function')) {    
       try {       // A+规定,声明then = x的then方法     
          let then = x.then;       // 如果then是函数,就默认是promise了   
          if (typeof then === 'function') {          // 就让then执行 第一个参数是this   后面是成功的回调 和 失败的回调      
               then.call(x, y => {   
                  // 成功和失败只能调用一个     
                  if (called) return;   
                  called = true;      
              
              // resolve的结果依旧是promise 那就继续解析    
                 resolvePromise(promise2, y, resolve, reject);         
               }, err => {      
             // 成功和失败只能调用一个    
              if (called) return;       
                  called = true;     
                  reject(err);// 失败了就失败了    
              })  
          }  else { 
              resolve(x); // 直接成功即可    
            }   
        } catch (e) {     
            // 也属于失败    
               if (called) return;   
                called = true;      
                 // 取then出错了那就不要在继续执行了  
               reject(e);     
           } 
      } else {     resolve(x);   } }

 

posted on 2019-10-17 08:22  不锈钢子  阅读(281)  评论(0编辑  收藏  举报