拉勾教育学习第一周——Promise

101 阅读4分钟

Promise 是异步编程的一种解决方案

Promise构造函数接受一个函数作为参数,该函数的两个参数分别是 resolve 和 reject

resolve函数的作用: 将Promise对象的状态从“未完成”变为“成功”(即从Pending变为Fulfilled),在异步操作成功时调用,并将异步操作的结果,作为参数传递出去

reject 函数的作用: 将Promise对象的状态从“未完成”变为“失败”(即从Pending变为Rejected),在异步操作失败时调用,并将异步操作报出的错误,作为参数传递出去

可以用抛出异常来代替reject,比如 throw new Error('error');


then()

接受两个回调函数作为参数。第一个参数是Fulfilled状态的回调函数,第二个参数(可选)是Rejected状态的回调函数 第一个回调函数接收Promise对象resolve的参数为参数,第二个回调函数接收Promise对象reject的参数为参数

then方法返回的是一个新的Promise实例(不是原来那个Promise实例),因此可以采用链式写法,即 then 方法后面再调用另一个 then 方法,即第二个then中res的值等于前一个then中的回调函数返回的值

要在then的回调再执行异步操作,需要在里面在返回一个promise实例

new Promise((res, rej) => {
  res('res');
})
.then(value => {
  return Promise.resolve(123)
}, reason => {})
.then(value => {
  console.log(value) // 123
})

catch()

catch 相当于then(null, rejection) 或 .then(undefined, rejection) ,是发生错误时的回调函数

then方法没写onRejected回调函数相当于将错误抛给后面 .then( value => {} ) // 相当于 .then( value => {}, reason => {throw reason} )

promise 抛出一个错误,就被 catch 方法指定的回调函数捕获

reject 方法的作用,等价于抛出错误

如果Promise状态已经变成 Fulfilled,再抛出错误是无效的。即在 resolve 语句后面,再抛出错误,不会被捕获,等于没有抛出。因为Promise 的状态一旦改变,就永久保持该状态,不会再变了(状态不会再变,但是resolve和reject后面的代码仍会继续执行)

Promise 对象的错误会一直向后传递,直到被捕获为止。也就是说,错误总是会被下一个 catch 语句捕获

catch方法要好于then方法里reject状态的回调函数,因为可以捕获前面 then 方法执行中的错误,也更接近同步的写法( try/catch )

var p = new Promise((resolve, reject) => {
	resolve('ok')
	throw new Error('test')
})
p.then(value => {
	console.log(value)
	x + 2
})
.catch(reason => console.log(reason))
// 'ok'
// ReferenceError: x is not defined

catch 方法返回的还是一个 Promise 对象,因此后面还可以接着调用then方法和catch方法

回调链上有多个then报错的话,catch只能捕捉它之前的第一个


finally()

不管promise最后的状态,都会执行finally方法指定的回调函数

回调函数不接受参数,没有办法知道前面的 Promise 状态到底是fulfilled还是rejected,回调函数里面的操作与状态无关的


静态方法 all()

用于将多个Promise实例,包装成一个新的Promise实例

接受一个数组作为参数,数组元素都是Promise对象的实例,如果不是,会自动调用Promise.resolve()转化为一个Promise实例

返回的Promise实例的状态由数组元素决定,分成两种情况。 (1)只有所有的数组元素的状态都变成 fulfilled,新的Promise实例的状态才会变成 fulfilled ,此时数组元素的返回值组成一个数组,传递给新的Promise实例的回调函数 (2)只要数组元素之中有一个被 rejected,新的Promise实例的状态就变成 rejected ,此时第一个被reject的实例的返回值,会传递给新的Promise实例的回调函数

let p1 = new Promise((res, rej) => {
res(1)
})
let p2 = new Promise((res, rej) => {
res(2)
})
let p3 = new Promise((res, rej) => {
res(3)
})
let p4 = new Promise((res, rej) => {
rej(4)
})
Promise.all([p1,p2,p3])
.then(value => console.log(value))
// [1,2,3]
Promise.all([p1,p2,p3,p4])
.catch(reason => console.log(reason))
// 4

fulfilled状态的结果顺序不会根据每个Promise实例状态改变的顺序而改变


静态方法 resolve()

将传入的参数转化Promise对象 相当于new Promise(resolve => resolve(value))

参数的各种情况:

  1. 参数是一个Promise实例,返回这个实例
  2. 参数是一个 thenable 对象,返回状态为fulfilled的Promise对象,并执行自带的then方法
  3. 其他对象或其他数据类型,返回状态为fulfilled的Promise对象