1、Promise

根本介绍及用法咱就不唠了,详见 传送门1

唠一唠Promise的特点

  • 两个特点

    • Promise对象的状态不受外界影响

      > Promise对象代表一个异步操作,共三个阶段,pending(进行中)、fulfilled(已胜利)、rejected(已失败)。也就是只有异步操作的后果才能够决定以后是哪一种状态,其余操作都无奈扭转状态,所以才叫Promise(承诺)。
    • 状态一旦扭转,就不会再变,任何时候都能够失去这个后果

那么看例子:

let p2 = new Promise((resolve, reject) => {  throw new Error('报错了');}).then(result => result).catch(e => e);// logundefined

后果是undefined,此处尽管进行了throw err,然而没有在catch进行具体的操作,而只是e=>e,还是返回一个Promise实例。

再看:

let p2 = new Promise((resolve, reject) => {  throw new Error('报错了');  })  .then(result => result)  .catch(e => e)  .then(() => {console.log('111')})  .catch(() => {console.log('222')})  .then(() => {console.log('333')})  .catch(() => {console.log('444')});    // log  111  333

也就是catch没有调用Promise.reject()扭转状态的话,Promise会始终默认走.then而不会走.catch。

这也是Promise中的重头戏,咱们在用Promise的时候可能会发现,当then函数中return了一个值,咱们能够持续then上来,不过是什么值,都能在下一个then中获取,还有,当咱们不在then中放入参数,例:promise.then().then(),那么其前面的then仍旧能够失去之前then返回的值。

为什么呢,传送门2

首先咱们要留神的一点是,then有返回值,then了之后还能在then,那就阐明之前的then返回的必然是个Promise

置信看完 传送门2 就不须要我多比比了,记得如果没扭转状态会始终默认走 then 而不会走 catch 就行了

看例子:

let p2 = new Promise((resolve, reject) => {  throw new Error('报错了');}).then(result => result)  .catch(e => {console.log(e);return Promise.reject('2')})  .then(() => {console.log('111')})  .catch(() => {console.log('222')})  .then(() => {console.log('333')})  .catch(() => {console.log('444')});    //log  Error: 报错了  at <anonymous>:2:9  at new Promise (<anonymous>)  at <anonymous>:1:10  222  333

后果来看,可知进行Promise.reject()后,Promise实例状态从pending变为rejected了,所以才会走catch,然而走了catch之后还是能够持续.then,但此时Promise实例的状态曾经定格为rejected了,无奈再扭转了。

先这样吧,后续补充,欢送斧正

2、实现Promise.all

留神两点:

1、先判断参数是否iterator;
2、非promise实例进行Promise.resolve()
3、如果全副胜利,状态变为 resolved,返回值将组成一个数组传给回调
4、只有有一个失败,状态就变为 rejected,返回值将间接传递给回调,且返回值也是新的 Promise 对象

第一遍:

// 第一遍function Promiseall(promises) {    // 先判断参数是否可遍历,也就是有无iterator接口    const iterator = Symbol.iterator    if(!promises[iterator]) return    return new Promise((resolve, reject) => {        const resolvearr = []        const rejectarr = []        for(let i of promises) {            // 如果不是promise实例,则应用Promsie.resolve()函数将其转换为promise实例            if(!(i instanceof Promise)) {                i = Promise.resolve(i)            }            i.then(res => { // 胜利,将返回放进resolvearr数组                resolvearr.push(res)            }).catch( err => { // 报错,将谬误放进rejectarr数组                rejectarr.push(err)            })        }        setTimeout(() => {            // 判断rejectarr长度            // 如果为0, 则返回resolve(resolvearr);            // 如果不为0,则示意有一个实例报错,所以将报错的那一个示例返回            return rejectarr.length === 0?resolve(resolvearr) : reject(rejectarr[0])        })    })}// testconst p1 = new Promise(res => res(1))const p2 = new Promise((res,rej) => rej(2))const p3 = new Promise((res,rej) => rej(3))const p4 = '4'const result = Promiseall([p1,p2,p3,p4])                .then(res => {console.log(res)})                .catch(rej => {console.log(rej)})console.log(result)

几个问题:
1、all为Promise的动态函数
2、reject数组duck不用
3、应用push将后果放入数组的话不能保障返回值是按程序的
4、长度判断应该放在.then里,绝对外围的一部分
5、留神到.catch里return的是reject(err)而不是间接return err,因为要返回Promise实例


以下为针对以上问题改过后的版本,欢送斧正:

// 别间接用all,有可能会被Promise本身的all笼罩Promise.alll = function(promises) {    // 1、先判断是否iterator;2、非promise实例进行Promise.resolve()    const iterator = Symbol.iterator    if (!promises[iterator]) return    let count = 0    // 返回的是一个Promise实例,所以没有.then或.catch    return new Promise((resolve, reject) => {        // 定义数组接管每一个Promise实例的返回        const resolveArr = []        for (let i = 0; i < promises.length; i++) {            // 判断参数是否为Promise实例,不是则应用Promise.resolve()将其转换为实例            if (!(promises[i] instanceof Promise)) {               promises[i] = Promise.resolve(promises[i])            }            promises[i].then(res => {                // 不应用push,是因为要保障按程序输入                resolveArr[i] = res                count++                // 长度判断?外围?判断arr与参数长度                if (count === promises.length) {                  return resolve(resolveArr)                }            }).catch(err => {                // 留神返回的是Promise实例,所以要调用reject办法,而不是间接return err                return reject(err)            })        }    })}// test// testlet p1 = new Promise(res => res(1))let p2 = new Promise((res,rej) => res(2))let p3 = new Promise((res,rej) => res(3))let p4 = '4'Promise.alll([p1,p2,p3,p4])       .then(res => {console.log(res)})       .catch(rej => {console.log(rej)})




最初鸣谢 cvSoldiel 的指导