Promise基本概念
基本概念
promise就是javscript中一种用于处理异步操作的对象
Promise的三种状态:
1、pending(进行中):操作没有完成,也没有失败,正在进行中或等待某件事情发生。
2、Fulfilled(已完成):操作已经完成并返回了一个结果。
3、Rejected(以失败):操作未能发成,发生了某种错误或问题。
Promise 对象只有:从 pending 变为 fulfilled 和从 pending 变为 rejected 的状态改变。只要处于 fulfilled 和 rejected ,状态就不会再变了即 resolved(已定型)。
状态的缺点:
- 无法取消 Promise ,一旦新建它就会立即执行,无法中途取消。
- 如果不设置回调函数,Promise 内部抛出的错误,不会反应到外部。
- 当处于 pending 状态时,无法得知目前进展到哪一个阶段(刚刚开始还是即将完成)。
Promise的链式调用规则:
Promise的
链式调用
是指:
- 在一个
Promise
的.then() 方法
中返回一个新的Promise,然后可以继续在这个新的Promise上调用.then() 方法
。- 这种方式可以:让我们可以把多个异步操作串联起来,依次处理,避免回调地狱。
Promise的静态方法
Promise.then()
then 方法接收两个函数作为参数,第一个参数是 Promise 执行成功时的回调,第二个参数是 Promise 执行失败时的回调,两个函数只会有一个被调用。
Promise.all(iterable):
接受一个可迭代对象(通常是一个数组)作为参数,其中每个元素都是一个 Promise。
只有当所有的 Promise 都完成时,返回的 Promise 才会被完成,结果是一个包含所有结果的数组
如果有任何一个Promise被拒绝,Promise.all会立即返回一个被拒绝的Promise
async和await
async和await是JavaScript中用于处理异步操作的关键字。
它们让你能够像写同步代码那样编写异步代码,使得代码更加清晰和易读。
async 函数
async是用来定义一个异步函数的关键字。
一个函数一旦被定义为 async,它就会自动返回一个 Promise,而不论你在函数中实际返回的是什么。
await 关键字
await只能在async函数内部使用。
它用于等待一个Promise完成,并获得Promise解决的值
使用await,就像在告诉JS:“等一下,等这个Promise完成了,再继续执行后面的代码。”
async 和 await 的好处:
- 更易读:它让你可以像写同步代码一样写异步代码,不需要再用.then()链式调用,代码逻辑更直观
- 错误处理:你可以使用try...catch语句来处理异步操作中的错误,这样比处理Promise的.catch()更加清晰。
手写Promise
const PENDING = 'PENDING'
const FULFILLED = 'FULFILLED'
const REJECTED = 'REJECTED'
// 完整版
class myPromise {
constructor(executor) {
this.status = PENDING
this.value = undefined
this.reason = undefined
//当存在异步回调时,先记录下来,等到前一个异步回调执行完成后再取出执行
this.onResolvedCallbacks = []
this.onRejectedCallbacks = []
//通过调用resolve和reject来进行状态的流转
let resolve = (value) => {
if (this.status === PENDING) {
this.status = FULFILLED
//记录下resolve里面传进来的参数值,这也是下面then的第一个回调参数onFulfilled中的参数
this.value = value
this.onResolvedCallbacks.forEach((fn) => fn())
}
}
let reject = (reason) => {
if (this.status === PENDING) {
this.status = REJECTED
//记录下reject里面传进来的参数值,这也是下面then的第二个回调参数onRejected中的参数
this.reason = reason
this.onRejectedCallbacks.forEach((fn) => fn())
}
}
try {
executor(resolve, reject)
} catch (error) {
reject(error)
}
}
then(onFulfilled, onRejected) {
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : (value) => value
onRejected =
typeof onRejected === 'function'
? onRejected
: (error) => {
throw error
}
let promise2 = new myPromise((resolve, reject) => {
if (this.status === FULFILLED) {
//直接调用
setTimeout(() => {
try {
let x = onFulfilled(this.value)
this.resolvePromise(promise2, x, resolve, reject)
} catch (error) {
reject(error)
}
}, 0)
}
if (this.status === REJECTED) {
//直接调用
setTimeout(() => {
try {
let x = onRejected(this.reason)
this.resolvePromise(promise2, x, resolve, reject)
} catch (error) {
reject(error)
}
}, 0)
}
//执行.then()的时候,Promise实例化的部分可能存在异步,因此需要先把then里面的执行单独开辟一个空间存起来,然后等实例化的部分执行到resolve的时候,就拿出来执行
//单独开辟一个空间是为了保证他们的执行顺序,每一个执行都是一次独立的tick
if (this.status === PENDING) {
//储存函数
this.onResolvedCallbacks.push(() => {
setTimeout(() => {
try {
//x是then里面第一个参数onFulfilled的返回值
//这里调用onFulfilled,先执行onFulfilled函数体,然后拿到onFulfilled的返回值赋值给x
let x = onFulfilled(this.value)
//this.resolvePromise针对x的情况做处理
this.resolvePromise(promise2, x, resolve, reject)
} catch (error) {
reject(error)
}
}, 0)
})
this.onRejectedCallbacks.push(() => {
setTimeout(() => {
try {
let x = onRejected(this.reason)
this.resolvePromise(promise2, x, resolve, reject)
} catch (error) {
reject(error)
}
}, 0)
})
}
})
return promise2
}
catch(onRejected) {
return this.then(null, onRejected)
}
resolvePromise(promise2, x, resolve, reject) {
//promise2是then的返回值,x是then里面参数回调的返回值,不应该是同一个引用
if (promise2 === x) {
//链式调用类型检测失败
return reject(new TypeError('Chaining cycle detected for promise'))
}
let called = false
//typeof x === 'object'说明x是promise,说明是then的参数回调返回了一个promise
//例如:new Promise().then((value) => {
// return new myPromise(resolve=>{
// resolve(1)
// })
// })
//x就是 new myPromise(resolve=>{
// resolve(1)
// })
if (x !== null && (typeof x === 'object' || typeof x === 'function')) {
try {
let then = x.then
if (typeof then === 'function') {
//call的作用 ===> this指向x,并调用then()
then.call(
x,
//onFulfilled then的第一个参数
(y) => {
//called是为了确保这里只执行一次
if (called) return
called = true
this.resolvePromise(promise2, y, resolve, reject)
},
//onRejected then的第二个参数
(error) => {
if (called) return
called = true
reject(error)
}
)
} else {
//typeof x === 'function'就直接传给resolve,流转状态
resolve(x)
}
} catch (error) {
if (called) return
called = true
reject(error)
}
} else {
resolve(x)
}
}
}
// 测试用例
const asyncOperation = new myPromise((resolve, reject) => {
setTimeout(() => {
resolve('异步逻辑 等待1s')
console.log('异步promise')
}, 1000)
})
asyncOperation
.then((value) => {
console.log('then:', value)
//若这里是return 1223456 执行.then()时就是pending状态,就存起来
//下面这种返回了一个Promise,也是先存起来;取出来调用时,发现传入的x是一个Promise,就执行了x.then(),相当于循环处理
return new myPromise((resolve, reject) => {
//这里执行到x.then()之前,这个Promise调用了resolve,状态变为fulfilled,因此.then()的逻辑中会直接调用条件为FULFILLED中的函数体
// resolve(123456)
//如果是异步的调用resolve,
//那么这里执行到x.then()之前,这个Promise实例化还没有完成,状态时依旧是pending,那么就存起来,等到Promise实例化完成后,调用了resolve时,取出来再调用这个then()的处理逻辑函数
setTimeout(() => {
resolve('异步逻辑 123456')
}, 1000)
})
})
.then((res) => console.log('res', res))
.then((value) => {
console.log('then:', value)
return `1`
})
.then((value) => {
console.log('Second then:', value)
return new myPromise((resolve, reject) => {
setTimeout(() => {
resolve('2. 第二个then的返回')
}, 500)
})
})
.then((value) => {
console.log('Third then:', value)
throw new Error('3. 第三个then会报一个错误')
})
.catch((error) => {
console.error('Catch:', error.message)
})