异步编程
JavaScript代码在执行的时候是单线程的,可以理解为只能按照代码出现的顺序,从上到下一行一行的执行,但是遇到了异步的行为,比如定时器,那就需要等到同步代码执行完成后的一段时间里再去执行异步代码。
Promise
Promise首先是一个对象,它通常用于描述现在开始执行,一段时间后才能获得结果的行为(异步行为),内部保存了该异步行为的结果。然后,它有一个有状态的对象:
-
pending:待定
-
fulfilled:兑现
-
rejected:拒绝 一个Promise只有这3种状态,且状态的转换过程有且只有2种:
-
pending到fulfilled
-
pending到rejected 可以通过Promise构造器创建一个Promise
const promise = new Promise((resolve, reject) => {
resolve('哈哈哈')
})
传递给new Promise的是executor执行器、当Promise被创建的时候,executor会立即同步执行。executor函数里通常做了2件事情:初始化一个异步行为和控制状态的最终转换。
const promise = new Promise((resolve, reject) => {
setTimeout(()=>{
resolve()
},1000)
})
如上代码所示,setTimeout函数用来描述一个异步行为,而resolve用来改变装填。
executor函数包含2个参数,他们都是回调函数,用于控制Promise的状态转换。
- resolve:用来将状态pending转换成fulfilled
- reject:用来将状态pending转换成rejected 一个promise的状态一旦被转换过,则无法再变更
const promise = new Promise((resolve, reject) => {
setTimeout(()=>{
resolve('哈哈')
resolve('哈哈11')
reject('哈哈222')
},1000)
})
console.log(promise) // Promise {<fulfilled>: "哈哈"}
可以看到执行2次resolve函数,1次reject函数,但是promise的最终结果只取了第一次的resolve
由new Promise构造器返回的Promise对象具有如下内部属性:
- PromiseState:最初是pending,resolve被调用的时候变为fulfilled,或者reject被调用时会变为rejected
- PromiseResult:最初是undefined,resolve(value)时被调用变为value,或者在reject(error)被调用改为error。
Promise实例方法
Promise.prototype.then()
Promise.prototype.then()将用于Promise实例添加处理程序的函数。它接受2个可选的参数:
- onResolved:状态由pending转换成fulfilled时执行
- onRejected:状态由pending转换成rejected时执行
function onResolved(res){
console.log(`resolved${res}`) //resolved哈哈哈
}
function onRejected(err){
console.log(`rejected${err}`)
}
new Promise((resolve, reject) => {
resolve('哈哈哈')
}).then(onResolved,onRejected)
因为状态的变化只有2种,所以onResolved和onRejected在执行的时候必定是互斥。
new Promise((resolve, reject) => {
resolve()
}).then(res => {})
new Promise((resolve, reject) => {
reject()
}).then(null, err => {})
如果给then()函数传递来了非函数参数,则会默认忽略
Promise.prototype.catch()
Promise.prototype.catch()用于给Promise对象添加拒绝处理程序。只接受一个参数:onRejected函数。实际上,下面这两种写法是等效的:
function onRejected(err){}
new Promise((resolve, reject) => {
reject()
}).catch(onRejected)
new Promise((resolve, reject) => {
reject()
}).then(null, onRejected)
Promise.prototype.finally()
Promise.prototype.finally()用于给Promise对象添加onFinally函数,这个函数主要是做一些清理的工作,只有状态变化的时候才会执行该函数
function onFinally() {
console.log('哈哈哈') // 并不会执行
}
new Promise((resolve, reject) => {
}).finally(onFinally)
因为onFinally函数是没有任何参数的,所以在其内部其实并不知道该Promise的状态是怎么样的
链式调用
new Promise((resolve, reject) => {
resolve()
}).then(() => {
console.log('A')
new Promise((resolve, reject) => {
resolve()
}).then(() => {
console.log('B')
}).then(() => {
console.log('C')
})
}).then(() => {
console.log('D')
})
基于onResolved生成一个新的Promise
Promise.prototype.then()会返回一个新的Promise
let p1 = new Promise((resolve, reject) => {
resolve(3)
})
let p2 = p1.then(() => 6)
setTimeout(console.log, 0, p1) //Promise {<fulfilled>: 3}
setTimeout(console.log, 0, p2) //Promise {<fulfilled>: 6}
可以看到p1和p2的内部PromiseResult是不一样,说明p2是一个新的Promise实例。
新产生的Promise会基于onResolved的返回值进行构建,构建的时候其实是把返回值传递给Promise.resolve()生成的新实例。
如果.then()没有提供onResolved这个处理程序,则Promise.resolve()会基于上一个是咯resolve后的值来初始化一个新的实例
let p1 = new Promise((resolve, reject) => {
resolve(3)
})
let p2 = p1.then()
setTimeout(console.log, 0, p2) // Promise {<fulfilled>: 3}
如果onResolved处理程序没有返回值,那么返回的新实例的内部值会是undefined:
let p1 = new Promise((resolve, reject) => {
resolve(3)
})
let p2 = p1.then(() => {})
setTimeout(console.log, 0, p2) // Promise {<fulfilled>: undefined}
写不下去了,剩下的自行理解