JavaScript进阶讲解十六—>Promise

66 阅读5分钟

Promise三个状态

  1. pending: 初始状态,既没有被兑现,也没有被拒绝(当执行executor中的代码时,处于该状态)
  2. fulfilled:操作成功完成(执行了resolve时,处于该状态)
  3. rejected:操作失败(执行了reject时,处于该状态)
function requestData(url) {
    return new Promise((resolve, reject) => {
        if (url === '123') {
            resolve('成功')
        } else {
            reject('失败')
        }
    })
}

requestData('123').then(res => {
    console.log(res); // 成功
}).catch(err => {
    console.log(err);
})

requestData('321').then(res => {
    console.log(res);
}).catch(err => {
    console.log(err); // 失败
})

Promise的Executor

Executor是在创建Promise时需要传入的一个回调函数,这个回调函数会被立即执行,并且传入两个参数

new Promise((resolve, reject) => {
    console.log('Executor');
})
// then中接收两个参数,第二个是失败的回调
// new Promise((resolve, reject) => {
//     console.log('Executor');
// }).then(res => {
//     console.log('res', res);
// }, err => {
//     console.log('err', err);
// })

通常我们会在Executor中确定我们的Promise状态

  1. 通过resolve,可以兑现(fulfilled)Promise的状态,我们也可以称之为已决议(resolved)
  2. 通过reject,可以拒绝(reject)Promise的状态
  3. 一旦状态被确定下来,Promise的状态会被 锁死,该Promise的状态是不可更改的

Promise的resolve参数

  1. 传入的是普通的值或者对象,那么这个值会作为then回调的参数
new Promise((resolve, reject) => {
    resolve('11')
}).then(res => {
    console.log('res', res); // 11
}, err => {
    console.log('err', err);
})
  1. 传入的是另外一个Promise,那么这个新Promise会决定原Promise的状态
new Promise((resolve, reject) => {
    resolve(new Promise((resolve1, reject1) => {
        // 如果这里没有调resolve1, 或者reject1,那么整个状态都将是pending状态
        // 换句话说就是:这个Promise会决定原Promise的状态
    }))
}).then(res => {
    console.log('res', res);
}, err => {
    console.log('err', err);
})
  1. 传入的是一个对象,并且这个对象有实现then方法,那么会执行该then方法,并且根据then方法的结果来决定Promise的状态
new Promise((resolve, reject) => {
    resolve({
        then(resolve1, reject1) {
            resolve1('222')
        }
    })
}).then(res => {
    console.log('res', res); // 222
}, err => {
    console.log('err', err);
})

Promise的then方法

then方法是Promise对象上的一个方法:它其实是放在Promise的原型上的 Promise.prototype.then

console.log(Object.getOwnPropertyDescriptors(Promise.prototype));

then方法接受两个参数:

  1. fulfilled的回调函数:当状态变成fulfilled时会回调的函数
  2. reject的回调函数:当状态变成reject时会回调的函数

then方法多次调用

const promise = new Promise((resolve, reject) => {
    resolve('1')
})

// 这三个都会执行
promise.then(res1 => {
    console.log('res1', res1);
})

promise.then(res2 => {
    console.log('res2', res2);
})

promise.then(res3 => {
    console.log('res3', res3);
})

then方法 传入的回调函数,可以有返回值

  1. 返回一个普通的值:这个普通的值被作为一个新的Promise的resolve的值
const promise = new Promise((resolve, reject) => {
    resolve('1')
})

promise.then(res => {
    return '2'
}).then(res => {
    console.log(res); // 2
})

这段代码的两个then的使用,可以上面then多次调用的代码不一样哟

  1. 返回一个Promise
const promise = new Promise((resolve, reject) => {
    resolve('1')
})

promise.then(res => {
    return new Promise((resolve, reject) => {
        resolve('2')
    })
}).then(res => {
    console.log(res); // 2
})
  1. 返回一个对象,并且这个对象有实现then方法
const promise = new Promise((resolve, reject) => {
    resolve('1')
})

promise.then(res => {
    return {
        then(resolve, reject) {
            resolve('2')
        }
    }
}).then(res => {
    console.log(res); // 2
})

Promise的catch方法

const promise = new Promise((resolve, reject) => {
    reject('1')
})

promise.catch(err => {
    console.log(err);
})

catch方法 返回值

const promise = new Promise((resolve, reject) => {
    reject('1')
})

// 在catch中return,他也相当于是执行resolve,所以他会到then,除非手动reject或者throw
promise.then(() => {
    console.log('then');
}).catch(() => {
    return '222'
}).then(res => {
    console.log('res', res);
}).catch((err) => {
    console.log('err', err);
})

Promise的finally方法

finally是在ES9中新增的一个特性:表示无论Promise对象无论变成fulfilled还是reject状态,最终都会被执行的代码。finally方法是不接收参数的,因为无论前面是fulfilled状态,还是reject状态,它都会执行。

const promise = new Promise((resolve, reject) => {
    resolve('1')
})

promise.then(() => {
    console.log('then');
}).catch(() => {
    console.log('catch');
}).finally(() => {
    console.log('finally');
})

Promise的resolve方法

在之前讲的then,catch,finally这三个是实例方法也叫对象方法,接下来我们来看他的类方法。

// 将一个对象转为promise
const promise = Promise.resolve({ name: 'xt' })

// 相当于

const promise1 = new Promise(resolve => {
    resolve({ name: 'xt' })
})

resolve参数:

  1. 参数是一个普通的值或者对象
  2. 参数本身是Promise
  3. 参数是一个thenable

Promise的reject方法

const promise = Promise.reject({ name: 'xt' })

// 相当于
const promise1 = new Promise((resolve, reject) => {
    reject({ name: 'xt' })
})

Promise.reject传入的参数无论是什么形态,都会直接作为reject状态的参数传递到catch的

Promise的all方法

  1. 它的作用是将多个Promise包裹在一起形成一个新的Promise
  2. 新的Promise状态由包裹的所有Promise共同决定
  3. 结果值是数值
const promise1 = new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve(1)
    }, 1000);
})

const promise2 = new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve(2)
    }, 2000);
})

const promise3 = new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve(3)
    }, 3000);
})

// 只要有一个promise为rejected,那么所有的promise为rejected
Promise.all([promise1, promise2, promise3]).then(res => {
    console.log(res); // [ 1, 2, 3 ]
}).catch(err => {
    console.log(err);
}))

Promise的allSettled方法

因为all方法我们上面说过只要有一个promise为rejected,那么所有的promise为rejected,那么对于resolved的,以及依然处于pending状态的Promise,我们是获取不到对应的结果的,所以在ES11中有了Promise.allSettled。

该方法会在所有的Promise都有结果(settled),无论是fulfilled,还是reject时,才会有最终的状态,并且这个Promise的结果一定是fulfilled的

const promise1 = new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve(1)
    }, 1000);
})

const promise2 = new Promise((resolve, reject) => {
    setTimeout(() => {
        reject(2)
    }, 2000);
})

const promise3 = new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve(3)
    }, 3000);
})

Promise.allSettled([promise1, promise2, promise3]).then(res => {
    console.log('res', res); // [{ status: 'fulfilled', value: 1 },{ status: 'rejected', reason: 2 },{ status: 'fulfilled', value: 3 }]
}).catch(err => {
    console.log('res', err);
})

Promise的race方法

如果有一个Promise有了结果,我们就希望决定最终新Promise的状态,那么可以使用race方法

const promise1 = new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve(1)
    }, 1000);
})

const promise2 = new Promise((resolve, reject) => {
    setTimeout(() => {
        reject(2)
    }, 2000);
})

const promise3 = new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve(3)
    }, 3000);
})

Promise.race([promise1, promise2, promise3]).then(res => {
    console.log('res', res); // 1
}).catch(err => {
    console.log('res', err);
})

Promise的any方法

  1. any方法是ES12中新增的方法,和race方法是类似的。
  2. any方法会等到一个fulfilled状态,才会决定新Promise的状态
  3. 如果所有的Promise都是reject的,那么也会等到所有的Promise都变成rejected状态
  4. 如果所有的Promise都是reject的,那么会报一个AggregateError的错误
const promise1 = new Promise((resolve, reject) => {
    setTimeout(() => {
        reject(1)
    }, 1000);
})

const promise2 = new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve(2)
    }, 2000);
})

const promise3 = new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve(3)
    }, 3000);
})

Promise.any([promise1, promise2, promise3]).then(res => {
    console.log('res', res); // 2
}).catch(err => {
    console.log('res', err);
})