前端 promise面试题

89 阅读18分钟

区别实例对象与函数对象

实例对象:new函数产生的对象,称为实例对象,简称对象

函数对象:将函数作为对象使用

function Fn() {} // Fn是函数
const fn = new Fn() // Fn是构造函数  fn是实例对象
// ()左边的是函数   .点左边的是对象
console.log(Fn.prototype) // Fn是函数对象  Fn是函数但在点左边,所以是函数对象
Fn.bind({}) // Fn是函数对象
$('#test') // jQuery函数
$.get('/test') // jQuery函数对象

两种类型的回调函数

同步回调

理解:立即执行,完全执行完了才结束,不会放入回调队列中

例子:数组遍历相关的回调函数、Promise的excutor函数

const arr = [1,3,4]
arr.forEach(item => {
   // 遍历回调,是同步回调函数,arr遍历完才执行下面的
   console.log(item)
})
console.log('forEach()之后')
// 输出 1 3 4 forEach()之后

异步回调

理解:不会立即执行,会放入回调队列中执行

例子:定时器回调,aiax回调,Promise的成功或失败

setTimeout(()=> {
    console.log('timeout callback()')
}, 0)
console.log('setTimeout()之后')
// 输出 setTimeout()之后  timeout callback()

JS的error错误处理

错误类型

  1. Error: 所有错误的父类型

  2. ReferenceError : 引用的变量不存在

    console.log(a)
    // 报错 Uncaught ReferenceError :a is not defined
    // 错误是ReferenceError
    // a is not defined是错误的描述信息message
    
  3. TypeError: 数据类型不正确的错误

    let b 
    console.log(b.xxx)
    // 报错 TypeError: cannot read property 'xxx' of undefined
    //  cannot read property 'xxx' of null 不能再null上面读取xxx属性
    
    b={}
    b.xxx() // TypeError: b.xxx is not a function
    
  4. RangError: 数据值不在其允许的范围内

    function fn() {
      fn()
    }
    fn()
    // RangError: Maximum call stack size exceeded
    // Maximum call stack size exceeded 最大调用栈的大小超过了
    
  5. SyntaxError: 语法错误

    const c = " "" "
    // SyntaxError:Unexpected string 字符串格式不对
    

错误处理

捕获错误:try ... catch

try {
  let d 
  console.log(d.xxx)
} catch (error) {
  // error是一个对象,有两个属性,message stack 
  console.log(error.message)// cannot read property 'xxx' of undefined
  console.log(error.stack)//TypeError: cannot read property 'xxx' of     undefined 和出错的位置
}
console.log('出错后也能执行')
// 出错后也能执行 
因为被try...catch 捕获处理了

抛出错误:throw error

function some() {
  if (Date.now()%2===1) {
    console.log('当前时间为奇数,可执行代码')
  } else {
    // 如果时间为偶数,由调用者处理
    throw new Error('当前时间为偶数,不可执行代码')
  }
}
// 捕获处理异常
try {
    some()
} catch (error) {
    alert(error.message)
}

错误对象

message属性:错误相关信息

stack属性:函数调用栈记录信息

二 Promise的理解和使用

Promise是什么

理解

1、主要用于异步计算 2、可以将异步操作队列化,按照期望的顺序执行,返回符合预期的结果 3、可以在对象之间传递和操作promise,帮助我们处理队列

1.抽象表达

Promise是JS中进行异步编程的新的解决方案

2.具体表达

从语法上来说:Promise是一个构造函数

从功能上来说:Promise对象用来封装一个异步操作并可以获取其结果

Promise的状态改变

1.pending变为resolved

2.pending变为rejected

说明:只有这两种改变,一个promise只能改变一次

​ 无论成功还是失败都会有一个结果数据‘

​ 成功的结果数据成为value,失败的结果数据称为reason

Promise使用的基本流程

首先新建一个Promise对象,传一个函数类型的参数,开始的状态为pending

然后在函数中会启动异步任务

如果成功,执行resolve()函数,promise对象变为resolved状态,然后调用成功的回调函数onResolved(用.then()指定),.then()执行后返回一个新的promise对象

如果失败,执行reject()函数,promise对象变为rejected状态,然后调用失败的回调函数onRejected(用.then()或.ctch()指定),执行后返回一个新的promise对象

Promise的基本使用

 <script>
        // 1.创建一个新的promise对象
        const p = new Promise((resolve, reject) => {
            // 执行器函数
            // 2.执行异步任务
            setTimeout(()=>{
                // 如果当前时间为偶数,成功,否则失败
                const time = Date.now()
                // 3.1 如果成功,调用resolve(value)
                if(time%2===0){
                    resolve('成功,time=' + time)
                } else {
                    // 3.2 如果失败,调用reject(reason)
                    reject('失败,time=' + time)
                }
            }, 1000)
        })

        p.then(
            value => {
                // 接收得到成功的value数据  onResolved
                console.log('成功的回调', value)
            },
            reason => {
                // 接收得到失败的reason数据 onRejected
                console.log('失败的回调', reason)
            }
        )
    </script>

为什么要用Promise

1.指定函数的方式更加灵活

(1)旧的:必须在启动异步任务前指定

(2)promise: 启动异步任务=》返回promise对象=》给promise对象绑定回调函数

​ (甚至可以在异步任务结束后指定多个)

2.支持链式调用,可以解决回调地狱问题

什么是回调地狱

回调函数嵌套调用,外部回调函数异步执行的结果是嵌套的回调函数执行的条件

涉及多个异步函数

doSomething(function(result){
  doSomethingElse(result, function(newResult){
    doThirdThing(newResult, function(finalResult){
      console.log('Got the final result:' + ginalResult)
    }, failureCallback)
  }, failureCallback)
}, failureCallback)

回调地狱的缺点

不便于阅读,不便于异常处理

解决方案

Promise链式调用

doSomething().then(function(result) {
  return doSomethingElse(result)
})
.then(function(newResult) {
  return doThirdThing(newResult)
})
.then(function(finalResult) {
   console.log('Got the final result:' + ginalResult)
})
.catch(failureCallback)

终极解决方案

async/await

async function request() {
  try {
    const result =await doSomething()
    const newResult = await doSomethingElse(result)
    const finalResult = await doThirdThing(newResult)
    console.log('Got the final result:' + ginalResult)
  } catch (error) {
     failureCallback(error)
  }
}

如何使用Promise

1.API

(1)Promise构造函数:Promisse(excutor){}

  • excutor函数: 执行器 (resolve, reject) => {}
  • resolve函数: 内部定义成功是调用的函数 value => {}
  • reject函数: 内部定义失败时调用的函数 reason => {}

说明:excutor会在Promise内部立即同步回调,异步操作在执行器中执行

(2)Promise.prototype.then 方法:(onResolved, onRejected)=> {}

  • ​ onResolved函数: 成功的回调函数 (value) => {}
  • ​ onRejected函数: 失败的回调函数 (reason)=> {}

说明:指定用于得到成功value的成功回调和用于得到失败reasond 的失败回调,返回一个 新的Promise 对象

​ (3)Promise.prototype.catch 方法:(onRejected)=> {}

​ onRejected函数: 失败的回调函数 (reason)=> {}

说明: then()的语法糖,相当于:then(undefined, onRejected)

​ (4) Promise.resolve方法: (value)=> {}

​ value: 成功的数据或者Promise对象

说明:返回一个成功或失败的promise对象

​ (5) Promise.reject方法:(reason)=> {}

​ reason: 失败的原因

说明:返回一个失败的promise对象

​ (6)Promise.all方法:(promises) => {}

​ promises:包含n个promise的数组或者直接是一个数值

说明:返回一个新的promise,只有所有的promise都成功才成功,只要有一个失败就直接失败

​ (7)Promise.race方法:(promises) => {}

​ promises:包含n个promise的数组或者直接是一个数值

说明:返回一个新的promise, 第一个完成的promise的结果状态就是最终的结果状态

2.Promise的几个关键问题

  • 如何改变promise的状态

    1. resolve(value): 如果当前是pending就会变为resolved
    2. reject(reason): 如果当前是pending就会变为rejected
    3. 抛出异常:如果当前是pending就会变为rejected
  • 一个promise指定多个成功或失败回调函数,都会调用吗?

    当promise改变为对应状态是都会调用

  • 改变promise状态和指定回调函数谁先谁后?

    1. 都有可能,正常情况下是先指定回调在改变状态,但也可以先改状态在指定回调

    2. 如何先改状态再指定回调?

      (1)在执行器中直接使用resolve()/reject()

      (2)延迟更长时间才调用then()

    3. 什么时候才能得到数据?

      (1)如果先指定的回调,那当状态发生改变时,回调函数就会调用,得到数据

      new Promise ((resolve, reject) => {
         setTimeout(() => { // 后改变的状态(同时指定数据),异步执行回调函数
            resolve(1)
         }, 1000)
      }).then( // 先指定回调函数,保存当前指定的回调函数
        value => {}
        reason => {console.log('reason', reason)}
      )
      

      (2)如果先改变的状态,那当指定回调是时,回调函数就会调用,得到数据

      new Promise ((resolve, reject) => {
         // 先改变的状态(同时指定数据)
            resolve(1)
      }).then( // 后指定回调函数,异步执行回调函数
        value => {}
        reason => {console.log('reason', reason)}
      )
      
  • promise.then()返回的新promise的结果状态右什么决定?

    1. 简单表达:由then()指定的回调函数执行的结果决定

    2. 详细表达:

      (1)如果抛出异常,新promise变为rejected, reason为抛出的异常

      (2)如果返回的是非promise的任意值,新promise变为resolved,value为返回的值

      (3)如果返回的是另一个新promise,此promise的结果就会成为新promise的结果

      new Promise ((resolve, reject) => {
        resolve(1)
      }).then(
        value => {
            console.log('onResolved1()', value)
            // return 2
            // return Promise.resolve(3)
            // return Promise.reject(4)
        }
        reason => {console.log('onRejected1()', reason)}
      ).then(
        value => {console.log('onResolved2()', value)}
        reason => {console.log('onRejected2()', reason)}
      

)

// 输出 onResolved1() 1
        onResolved2() undefined
 // 因为value => {console.log('onResolved1()', value)}这个函数执行了,没有抛出异常,所以就相当于return undefined ,所以value => {console.log('onResolved2()', value)}函数值是undefined
 // 如果value => {console.log('onResolved1()', value) return 2}
 // 结果值就是onResolved1() 1
 //         onResolved2() 2
 ```
  • promise如何串联多个操作任务

    1. promise的then()返回一个新的promise,可以看出then的链式调用

    2. 通过then()的链式调用串联多个同步/异步任务

      new Promise ((resolve, reject) => {
        setTimeout(() => {
          console.log('执行异步任务1')
          resolve(1)
        }, 1000)
      }).then(
        value => {
            console.log('任务1的结果', value)
            console.log('执行同步任务2')
            return 2
        }
      ).then(
        value => {
            console.log('任务2的结果', value)
            return new Promise ((resolve, reject) => {
                // 启动任务3(异步)
                setTimeout(() => {
                   console.log('执行异步任务3')
                   resolve(3)
                }, 1000)
            })
        }
      ).then(
        value => {
            console.log('任务3的结果', value)
        }
      )
      
      // 执行异步任务1
      // 任务1的结果 1
      // 执行同步任务2
      // 任务2的结果 2
      // 执行异步任务3
      // 任务3的结果 3
      
  • promise异常传透

    1. 当使用promise的then链式调用时,可以在最后指定失败的回调

    2. 前面任何操作出了异常,都会传到最后失败的回调函数中处理

      new Promise ((resolve, reject) => {
        // resolve(1)
        reject(1)
      }).then(
        value => {
            console.log('onResolved1()', value)
            return 2
        }
        // reason => {throw reason}抛出异常,reason为1,.then回调函数失败,向下找失败的promise回调函数
      ).then(
        value => {
          console.log('onResolved2()', value)
          return 3
        }
          // reason => {throw reason}抛出异常,reason为1,.then回调函数失败,向下找失败的promise回调函数
      ).then(
        value => {
          console.log('onResolved3()', value)
        }
          // reason => {throw reason}抛出异常,reason为1,.then回调函数失败,向下找失败的promise回调函数
      ).catch(
        reason => {
          console.log('onRejected1()', reason)
        }
      )
      
      // 输出 onRejected1() 1
      // 从.then()一步一步传透过来的,相当于.then()中写了reason=>{throw     reason}
      
  • 中断promise 链?

    1. 当使用promise的then 链式调用时,在中间中断,不在调用后面的回调函数

    2. 办法:在回调函数中返回一个pendding状态的promise对象

      new Promise ((resolve, reject) => {
        // resolve(1)
        reject(1)
      }).then(
        value => {
            console.log('onResolved1()', value)
            return 2
        }
        // reason => {throw reason}抛出异常,reason为1,.then回调函数失败,向下找失败的promise回调函数
      ).then(
        value => {
          console.log('onResolved2()', value)
          return 3
        }
          // reason => {throw reason}抛出异常,reason为1,.then回调函数失败,向下找失败的promise回调函数
      ).then(
        value => {
          console.log('onResolved3()', value)
        }
          // reason => {throw reason}抛出异常,reason为1,.then回调函数失败,向下找失败的promise回调函数
      ).catch(
        reason => {
          console.log('onRejected1()', reason)
          // throw reason
          // return Promise.reject(reason)
          return new Promise(() => {})
          // 返回一个pending的promise, 中断promise链
        }
      ).then(
        value => {
          console.log('onResolved3()', value)
        }
        reason => {
          console.log('onRejected2()', reason)
        }
      )
      // 输出 onRejected1()  1
      //     onResolved3() undefined
      

三 手写Promise

ES5

/**
 * 自定义Promise函数模块
 */
(function (window) {
    const PENDING = 'pending'
    const RESOLVED = 'resolved'
    const REJECTED = 'rejected'

    /*
    Promise构造函数
    excutor:执行器函数,同步执行
    */
    function Promise (excutor) {
        // 将当前promise对象保存起来
        const self = this
        // 给promise对象指定status状态属性,初始值为pending
        self.status = PENDING
        //  给promise对象指定一个用于存储结果数据的属性
        self.data = undefined
        // 每个元素的结构:{onResolved() {}, onRejected() {}}
        self.callbacks = []

        function resolve(value) {
            // 如果当前状态不是pending,直接结束
            if(self.status !== PENDING) {
                return
            }

            // 将状态改为resolved
            self.status = RESOLVED
            // 保存value数据
            self.data = value
            // 如果有待执行的callback函数,立即异步执行回调函数onResolved
            if (self.callbacks.length>0) {
                setTimeout(() => {// 放入队列中执行所有成功的回调
                    self.callbacks.forEach(callbacksObj => {
                        callbacksObj.onResolved(value)
                    })
                })
            }
        }
        function reject(reason) {
            // 如果当前状态不是pending,直接结束
            if(self.status !== PENDING) {
                return
            }
             // 将状态改为rejected
             self.status = REJECTED
             // 保存reason数据
             self.data = reason
             // 如果有待执行的callback函数,立即异步执行回调函数onRejected
             if (self.callbacks.length>0) {
                 setTimeout(() => {// 放入队列中执行所有成功的回调
                     self.callbacks.forEach(callbacksObj => {
                         callbacksObj.onRejected(reason)
                     })
                 })
             }
        }
        // 立即同步执行excutor
        try {
            excutor(resolve, reject)
        } catch (error) {
            // 如果执行器抛出异常,promise对象变为rejected状态
            reject(error)
        }
    }

    /* 
    Promise原型对象的then()
    指定成功和失败的回调函数
    返回一个新的promise对象
    */
    Promise.prototype.then = function (onResolved, onRejected) {
        const self = this;

        // 指定函数的默认值(必须是函数)
        onResolved = typeof onResolved === 'function'? onResolved : value => value;
        onRejected = typeof onRejected === 'function'? onRejected : reason => {throw reason};

        // 返回一个新的promise
        return new Promise((resolve, reject) => {
            /*
            执行指定的回调函数
            根据执行的结果改变return的promise的状态/数据
            */
            function handle(callback) {
                  /*
                    返回promise的结果由onResolved, onRejected执行结果决定
                    1.抛出异常,返回promise的结果失败,reason为异常
                    2.返回的是promise,返回promise的结果就是这个结果
                    3.返回的不是promise,返回promise为成功,value就是返回值
                    */
                   try {
                        const result = callback(self.data)
                        if(result instanceof Promise) {
                            // 2.返回的是promise,返回promise的结果就是这个结果
                            // result.then(
                            //     value => resolve(value), 
                            //     reason => reject(reason)
                            // )
                            result.then(resolve, reject)
                        } else {
                            // 3.返回的不是promise,返回promise为成功,value就是返回值
                            resolve(result)
                        }
                   } catch (error) {
                    // 1.抛出异常,返回promise的结果失败,reason为异常
                       reject(error)
                   }
            }

            if(self.status === RESOLVED) {
                // 当前promise是resolved状态
                // 立即异步执行成功的回调函数
                setTimeout(() => {
                    handle(onResolved)
                })
            } else if(self.status === REJECTED) {
                // 当前promise是rejected状态
                // 立即异步执行失败的回调函数
                setTimeout(() => {
                    handle(onRejected)
                })
            } else {
                // 当前promise是pending状态
                // 将成功和失败的回调函数保存callbacks容器中缓存起来
                self.callbacks.push({
                    onResolved(value) {
                        handle(onResolved)
                    },
                    onRejected(reason) {
                        handle(onRejected)
                    }
                })
            }
            
            
        })
        
    }

    /* 
    Promise原型对象的catch()
    指定失败的回调函数
    返回一个新的promise对象
    */
    Promise.prototype.catch = function (onRejected) {
        return this.then(undefined, onRejected)
    }

    /*
    Promise函数对象resolve方法
    返回一个指定结果value的成功的promise
    */
    Promise.resolve = function(value) {
        // 返回一个成功/失败的promise
        return new Promise((resolve, reject) => {
            // value 是promise
            if(value instanceof Promise) {
                // 使用value的结果作为promise的结果
                value.then(resolve, reject)
            } else {
                // value 不是promise => promise变为成功,数据是value
                resolve(value);
            }
            
        })
    }

    /*
    Promise函数对象reject方法
    返回一个指定结果的失败的promise
    */
    Promise.reject = function(reason) {
        // 返回一个失败的promise
        return new Promise((resolve, reject) => {
            reject(reason);
        })
    }

    /*
    Promise函数对象all方法
    返回一个promise,只有当所有promise都成功时才成功,否则失败
    */
    Promise.all = function(promises) {
        // 用来保存所有成功value的数组
        // 指定values数组的长度(等于promise的长度)
        const values = new Array(promises.length);

        // 用来保存成功promise的数量
        let resolvedCount = 0;
        // 返回一个新的promise
        return new Promise((resolve, reject) => {
            // 遍历获取每个promise的结果
            promises.forEach((p, index) => {
                Promise.resolve(p).then(
                    value => {
                        // 成功的数量加1
                        resolvedCount++

                        // p成功,把成功的value保存到values数组中
                        values[index] = value;
                        // 如果全部成功,将return的promise改为成功
                        if (resolvedCount === promises.length) {
                            resolve(values)
                        }
                        
                    },
                    reason => {
                        // 只要有一个失败了,return的promise就失败
                        reject(reason)
                    }
                )
            })
        })
    }

    /*
    Promise函数对象race方法
    返回一个promise,结果由第一个完成的promise决定
    */
    Promise.race = function(promises) {
        // 返回一个promise
        return new Promise((resolve, reject) => {
             // 遍历获取每个promise的结果
             promises.forEach((p, index) => {
                Promise.resolve(p).then(
                    value => {
                        // 一旦有一个成功,将return变为成功
                        resolve(value)
                    },
                    reason => {
                        // 一旦有一个失败,将return变为失败
                        reject(reason)
                    }
                )
            })    
        })
    }

    /*
    返回一个promise对象,在指定的时间后才确定结果
    */
   Promise.resolveDelay = function (value, time) {
              // 返回一个成功/失败的promise
            return new Promise((resolve, reject) => {
                setTimeout(() => {
                    // value 是promise
                    if(value instanceof Promise) {
                        // 使用value的结果作为promise的结果
                        value.then(resolve, reject)
                    } else {
                        // value 不是promise => promise变为成功,数据是value
                        resolve(value);
                    }
                }, time)
                
            })
   }

   /*
    返回一个promise对象,在指定的时间后才失败
    */
   Promise.rejectDelay = function (reason, time) {
           // 返回一个失败的promise
            return new Promise((resolve, reject) => {
                setTimeout(() => {
                    reject(reason);
                }, time);
            })
   }

    // 向外暴露Promise函数
    window.Promise = Promise
})(window)

ES6

class Promise类对象

constructor 容器

直接then方法是在原型对象上定义

static是在类对象上定义

/**
 * 自定义Promise函数模块
 */
(function (window) {
    const PENDING = 'pending'
    const RESOLVED = 'resolved'
    const REJECTED = 'rejected'

    class Promise {
        /*
        Promise构造函数
        excutor:执行器函数,同步执行
        */
        constructor(excutor) {
            // 将当前promise对象保存起来
            const self = this
            // 给promise对象指定status状态属性,初始值为pending
            self.status = PENDING
            //  给promise对象指定一个用于存储结果数据的属性
            self.data = undefined
            // 每个元素的结构:{onResolved() {}, onRejected() {}}
            self.callbacks = []

            function resolve(value) {
                // 如果当前状态不是pending,直接结束
                if(self.status !== PENDING) {
                    return
                }

                // 将状态改为resolved
                self.status = RESOLVED
                // 保存value数据
                self.data = value
                // 如果有待执行的callback函数,立即异步执行回调函数onResolved
                if (self.callbacks.length>0) {
                    setTimeout(() => {// 放入队列中执行所有成功的回调
                        self.callbacks.forEach(callbacksObj => {
                            callbacksObj.onResolved(value)
                        })
                    })
                }
            }
            function reject(reason) {
                // 如果当前状态不是pending,直接结束
                if(self.status !== PENDING) {
                    return
                }
                // 将状态改为rejected
                self.status = REJECTED
                // 保存reason数据
                self.data = reason
                // 如果有待执行的callback函数,立即异步执行回调函数onRejected
                if (self.callbacks.length>0) {
                    setTimeout(() => {// 放入队列中执行所有成功的回调
                        self.callbacks.forEach(callbacksObj => {
                            callbacksObj.onRejected(reason)
                        })
                    })
                }
            }
            // 立即同步执行excutor
            try {
                excutor(resolve, reject)
            } catch (error) {
                // 如果执行器抛出异常,promise对象变为rejected状态
                reject(error)
            }
        }

        /* 
        Promise原型对象的then()
        指定成功和失败的回调函数
        返回一个新的promise对象
        */
        then (onResolved, onRejected) {
            const self = this;

            // 指定函数的默认值(必须是函数)
            onResolved = typeof onResolved === 'function'? onResolved : value => value;
            onRejected = typeof onRejected === 'function'? onRejected : reason => {throw reason};

            // 返回一个新的promise
            return new Promise((resolve, reject) => {
                /*
                执行指定的回调函数
                根据执行的结果改变return的promise的状态/数据
                */
                function handle(callback) {
                    /*
                        返回promise的结果由onResolved, onRejected执行结果决定
                        1.抛出异常,返回promise的结果失败,reason为异常
                        2.返回的是promise,返回promise的结果就是这个结果
                        3.返回的不是promise,返回promise为成功,value就是返回值
                        */
                    try {
                            const result = callback(self.data)
                            if(result instanceof Promise) {
                                // 2.返回的是promise,返回promise的结果就是这个结果
                                // result.then(
                                //     value => resolve(value), 
                                //     reason => reject(reason)
                                // )
                                result.then(resolve, reject)
                            } else {
                                // 3.返回的不是promise,返回promise为成功,value就是返回值
                                resolve(result)
                            }
                    } catch (error) {
                        // 1.抛出异常,返回promise的结果失败,reason为异常
                        reject(error)
                    }
                }

                if(self.status === RESOLVED) {
                    // 当前promise是resolved状态
                    // 立即异步执行成功的回调函数
                    setTimeout(() => {
                        handle(onResolved)
                    })
                } else if(self.status === REJECTED) {
                    // 当前promise是rejected状态
                    // 立即异步执行失败的回调函数
                    setTimeout(() => {
                        handle(onRejected)
                    })
                } else {
                    // 当前promise是pending状态
                    // 将成功和失败的回调函数保存callbacks容器中缓存起来
                    self.callbacks.push({
                        onResolved(value) {
                            handle(onResolved)
                        },
                        onRejected(reason) {
                            handle(onRejected)
                        }
                    })
                }
                
                
            })
            
        }

        /* 
        Promise原型对象的catch()
        指定失败的回调函数
        返回一个新的promise对象
        */
        catch (onRejected) {
            return this.then(undefined, onRejected)
        }

        /*
        Promise函数对象resolve方法
        返回一个指定结果value的成功的promise
        */
        static resolve = function(value) {
            // 返回一个成功/失败的promise
            return new Promise((resolve, reject) => {
                // value 是promise
                if(value instanceof Promise) {
                    // 使用value的结果作为promise的结果
                    value.then(resolve, reject)
                } else {
                    // value 不是promise => promise变为成功,数据是value
                    resolve(value);
                }
                
            })
        }

        /*
        Promise函数对象reject方法
        返回一个指定结果的失败的promise
        */
        static reject = function(reason) {
            // 返回一个失败的promise
            return new Promise((resolve, reject) => {
                reject(reason);
            })
        }

        /*
        Promise函数对象all方法
        返回一个promise,只有当所有promise都成功时才成功,否则失败
        */
        static all = function(promises) {
            // 用来保存所有成功value的数组
            // 指定values数组的长度(等于promise的长度)
            const values = new Array(promises.length);

            // 用来保存成功promise的数量
            let resolvedCount = 0;
            // 返回一个新的promise
            return new Promise((resolve, reject) => {
                // 遍历获取每个promise的结果
                promises.forEach((p, index) => {
                    Promise.resolve(p).then(
                        value => {
                            // 成功的数量加1
                            resolvedCount++

                            // p成功,把成功的value保存到values数组中
                            values[index] = value;
                            // 如果全部成功,将return的promise改为成功
                            if (resolvedCount === promises.length) {
                                resolve(values)
                            }
                            
                        },
                        reason => {
                            // 只要有一个失败了,return的promise就失败
                            reject(reason)
                        }
                    )
                })
            })
        }

        /*
        Promise函数对象race方法
        返回一个promise,结果由第一个完成的promise决定
        */
        static race = function(promises) {
            // 返回一个promise
            return new Promise((resolve, reject) => {
                // 遍历获取每个promise的结果
                promises.forEach((p, index) => {
                    Promise.resolve(p).then(
                        value => {
                            // 一旦有一个成功,将return变为成功
                            resolve(value)
                        },
                        reason => {
                            // 一旦有一个失败,将return变为失败
                            reject(reason)
                        }
                    )
                })    
            })
        }

        /*
        返回一个promise对象,在指定的时间后才确定结果
        */
        static resolveDelay = function (value, time) {
                    // 返回一个成功/失败的promise
                    return new Promise((resolve, reject) => {
                        setTimeout(() => {
                            // value 是promise
                            if(value instanceof Promise) {
                                // 使用value的结果作为promise的结果
                                value.then(resolve, reject)
                            } else {
                                // value 不是promise => promise变为成功,数据是value
                                resolve(value);
                            }
                        }, time)
                        
                    })
        }

        /*
            返回一个promise对象,在指定的时间后才失败
            */
        static rejectDelay = function (reason, time) {
                // 返回一个失败的promise
                    return new Promise((resolve, reject) => {
                        setTimeout(() => {
                            reject(reason);
                        }, time);
                    })
        }
    }

    // 向外暴露Promise函数
    window.Promise = Promise
})(window)

四 async与await

async函数

函数的返回值为promise对象

promise对象的结果由async函数执行的返回值决定

// 成功       
async function f1() {
            return 1
        }
        const result = f1();
        console.log(result)
        // Promise {<resolved>: 1}
            // __proto__: Promise
            // [[PromiseStatus]]: "resolved"
            // [[PromiseValue]]: 1
// 失败
  async function f1() {
            throw 2
        }
        const result = f1();
        result.then(
            value => {
                console.log('onResolved', value)
            },
            reason => {
                console.log('onRejected', reason)
            }
        )
   // onRejected 2

await表达式

await命令后面是一个 Promise 对象,返回该对象的结果。如果不是 Promise 对象,就直接返回对应的值。

await右侧的表达式一般为promise对象,但也可以是其他的值

如果表达式是promisw对象,await返回的是promise成功的值

如果表达式是其他值,直接将此值作为await的返回值

// function f2() {
        //     return new Promise((resolve, reject) => {
        //         setTimeout(() => {
        //             resolve(5)
        //         }, 2000)
        //     })
        // }
        // async function f3() {
        //     // const value = await f2() // await右侧表达式是promise对象, 结果就是promise成的值
        //     const value = await 8 // await右侧表达式不是promise对象, 结果就是它本身
        //     console.log('value', value)
        // }
        // f3()

        function f2() {
            return new Promise((resolve, reject) => {
                setTimeout(() => {
                    reject(6)
                }, 2000)
            })
        }
        async function f3() {
            try {
                // const value = await f2() // await右侧表达式是promise对象, 结果就是promise成的值
                const value = await f1()
                console.log('value', value)
            } catch (error) {
                console.log('失败的结果', error)
            }
            // const value = await 8 // await右侧表达式不是promise对象, 结果就是它本身
            // console.log('value', value)
        }
        f3()

注意

await必须写在async函数中,但async函数中可以没有await

如果await的promise失败了,就会抛出异常,需要通过try...catch来捕获处理

1、async是干哈的?

定义异步函数(内部通常有异步操作),返回Promise对象(函数返回Promise→显式返回return的Promise;函数返回非Promise→隐式返回Promise.resolve()包装的return值;)

2、await在等啥?

只能放在async函数中,等待右侧表达式结果(函数→结果=return值;字符串→结果=字符串;)

3、await等到了又要干哈

阻塞后面的代码,先执行async外部的同步代码,同步代码执行完再回到async内部,拿到运算结果(表达式返回Promise→等待Promise对象fulfilled,再将resolve参数作为表达式的运算结果;表达式返回非Promise→直接作为表达式的运算结果;)