Promise
为了解决回调地狱而生
1.promise的基本使用:
一、使用
new Promise((resolve,reject) => {
setTimeout(() => {
console.log("OK")
},1000)
}).then(r => {
console.log(`then:${r}`)
}).catch(err => {
console.log(`catch:${err}`)
})
2.链式调用
function wait500(input){
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(input + 500)
},500)
})
}
function wait1000(input){
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(input + 1000)
},1000)
})
}
const p = new Promise((resolve, reject) => {
resolve(1)
})
p.then(wait500).then(wait1000).then(wait500).then(wait1000).then(res => {
console.log(`result:${res}`)
})
注:1.能被链式调用,要返回一个promise对象
2.使用链式调用,也要用一个promise对象
3.promise.all & promise.race
//全部执行完毕之后在进行操作
Promise.all([wait500,wait1000]).then(res => {
//res返回一个数组[f,f1,f2...]
console.log('all end' + res)
})
//一旦有执行完毕的,立刻操作
Promise.race([wait500,wait1000]).then(res => {
console.log('race end' + res)
})
二、手写Promise
1. promise的框架分析
- promise的状态:pending,fulfilled,rejected,状态一旦确定无法外部改变
- 状态流程默认状态为pending,状态流转pending => fulfilled,pending => rejected
- new Promise的时候的执行器executor()的参数:resolve,reject
- promise的value保存成功状态的的枚举? - undefined/thenable/promise
- promise的失败状态值? -reason
2. promise的接口分析
promise一定会有then方法,then接口来源?-两个callback:onFulfilled(value),onRejected(reason)
3.简单手撕一下
const PENDING = 'PENDING'
const FULFILLED = 'FULFILLED'
const REJECTED = 'REJECTED'
class Promise { // 类
constructor(executor) { // 构造
// 默认状态的处理: PENDING
this.status = PENDING
// 成功状态的值
this.value = undefined
// 失败状态的值
this.reason = undefined
// 成功状态的回调
let resolve = value => {
if (this.status === PENDING) {
this.status = FULFILLED
this.value = value
}
}
// 失败状态的回调
let reject = reason => {
if (this.status === PENDING) {
this.status = REJECTED
this.reason = reason
}
}
try {
executor(resolve, reject)
} catch (error) {
reject(error)
}
}
then(onFulfilled, onRejected) {
if (this.status === FULFILLED) {
onFulfilled(this.value)
}
if (this.status === REJECTED) {
onRejected(this.reason)
}
}
}
const promise = new Promise((resolve, reject) => {
resolve('成功')
}).then(data => {
console.log(data)
})
//打印:成功
但是考虑到传入用户传入异步的函数,可以做一下修改。写异步的时候,存在promise在调用then方法的时候并没有成功,而是在pending状态,所以在调用then方法的时候,应该吧回调函数再存一下,依次调用。 在考虑依次调用的时候,优先考虑队列queue数据结构
// 三个状态:PENDING FULFILLED REJECTED
const PENDING = 'PENDING'
const FULFILLED = 'FULFILLED'
const REJECTED = 'REJECTED'
class Promise {
constructor(executor) {
this.status = PENDING
this.value = undefined
this.reason = undefined
this.onResolvedCallbacks = []
this.onRejectedCallbacks = []
let resolve = value => {
if(this.status === PENDING){
this.status = FULFILLED
this.value = value
// 依次调用对应函数的执行
(this.onResolvedCallbacks || []).forEach(fn => fn())
}
}
let reject = reason => {
if(this.status === PENDING){
this.status = REJECTED
this.reason = reason
// 依次调用对应函数的执行
(this.onRejectedCallbacks || []).forEach(fn => fn())
}
}
try {
executor(resolve,reject)
}catch (e) {
reject(e)
}
}
then(onFulfilled,onRejected){
if (this.status === FULFILLED) {
onFulfilled(this.value)
}
if (this.status === REJECTED) {
onRejected(this.reason)
}
if(this.status === PENDING){
//当已经开始执行then函数,但是resolve的函数作为异步函数,还没有执行完毕,所以要把onResolvedCallbacks放在resolve之后来执行,所以保存上这些异步操作,等到resolve之后再进行依次执行
this.onResolvedCallbacks.push(() => {
onFulfilled(this.value)
})
this.onRejectedCallbacks.push(() => {
onRejected(this.reason)
})
}
}
}
const promise = new Promise((resolve, reject) => {
resolve('成功')
}).then(data => {
console.log(data)
})
当一个同步问题变成异步问题的时候,其实就是在执行的顺序上发生了一些 变化,那么我们就需要开辟一个新的空间来存储异步的内容,用空间解决时间问题。