7.7 KiB
7.7 KiB
Promise
进程/线程
进程: 独立的工厂, 相互隔离
线程: 共享工厂资源的工人, 既可以协作, 也可能互相抢资源
特性 | 进程 | 线程 |
---|---|---|
资源分配 | 独立的内存空间 | 共享进程的内存空间 |
独立性 | 完全独立,互不影响 | 共享资源,可能相互影响 |
通信方式 | 通过管道、消息队列等 | 直接共享内存 |
开销 | 创建和销毁开销较大 | 创建和销毁开销较小 |
适用场景 | 需要完全隔离的任务(如不同程序) | 需要高效协作的任务(如多任务处理) |
同步/异步
同步: 自上而下一行行执行
缺点: 会出现阻塞的情况, 一行代码运行慢会阻碍后面代码的执行
解决方法: ava/python: 多线程;nodejs: 异步
异步: 一段代码执行不会影响后面的代码
缺点: 无法通过return来设置返回值
解决方法: 回调函数
新问题: 回调地狱, 可读性差, 难调试
解决方法: promise : 一个特殊的容器, 用来存储异步调用的数据
promise
创建 Promise
/**
* 创建Promise时, 构造函数需要一个函数作为参数
* Promise构造函数的回调函数,会在创建Promise时执行,执行时有两个参数传递进去: resolve, reject
* resolve, reject, 也是两个函数, 通过这两个函数可以向Promise存储数据
* resolve 在执行正常时存储数据
* reject 在执行错误时存储数据
* 读取数据:
* 通过Promise实例的then方法来获取数据
* then需要两个回调函数作为参数
* 通过resolve存储的数据会通过第一个返回
* 通过reject或者出现异常,会通过第二个返回
*/
const mypromise = new Promise((resolve,reject)=>{
setTimeout(()=>{
resolve('hello')
// reject('err')
},3000)
})
mypromise.then((result)=>{
console.log('resolve:',result)
},(reason)=>{
console.log('reject或者异常:',reason)
})
Promise 的三种状态
/**
* Promise中维护了两个隐藏的属性
* - PromiseResult: 存储数据
* - PromiseState: 存储状态(三种)
* - pending 正在进行
* - fulfilled 完成 通过resolve存储数据
* - rejected 拒绝 通过reject存储数据或者异常
* state只能修改一次, 修改后永远不会变
*
* 流程:
* 当Promise创建时, PromiseState初始值为pending
* 通过resolve存储数据时, PromiseState变为fulfilled, PromiseResult变为存储的数据
* 通过reject存储数据或者异常, PromiseState变为rejected, PromiseResult变为存储的数据或异常数据
* 当通过then读取数据, 相当于为Promise设置了回调函数
* 如果PromiseState为fulfilled, 则调用then第一个回调函数来返回数据
* 如果PromiseState为rejected, 则调用第二个回调函数来返回数据
*/
// 这两种写法是等价的
const promise2 = new Promise((resolve,reject)=>{
resolve('hello')
})
// const promise2 = Promise.resolve('hello')
const promise3 = new Promise((resolve,reject)=>{
reject('err')
})
/**
* catch() 用法和then类似, 只需要一个回调函数作为参数
* catch() 只在Promise被拒绝时才执行, 相当于 then(null,reason=>{})
* 是用来专门处理Promise异常的方法
*/
promise3.catch((err)=>{
console.log(err)
})
/**
* finally() 无论正常或者异常,finally总会执行
* 但是finally的回调函数中不会接收到数据
* 一般用来写一些无论成功或失败总要执行的代码
*/
promise2.finally(()=>{
console.log('总会执行')
})
then (), catch () 的返回也是 Promise
/**
* promise
* then()
* catch()
* finally()
* 这三个方法都是返回一个新的promise
* then() catch() 返回的Promise会存储回调函数的返回值
* finally() 的返回值, 不会存储到新的Promise
*/
const sum = (a, b) => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(a + b)
}, 0)
})
}
const p2 = sum(1, 2).then()
console.log('p2:', p2)
const p3 = sum(1, 2).then(result => {
return result
})
console.log('p3:', p3)
sum(1, 2)
.then(result => {
return sum(result, 3)
})
.then(result => {
return sum(result, 4)
})
.then(result => {
console.log('链式调用:', result)
})
Promise 的链式调用
/**
* 链式调用,读取的是上一步的执行结果
* 如果上一步不是想要的, 则跳过当前的方法
*/
/**
* 当promise链式调用中,如果没有catch接收错误, 就会向外抛出
* throw new Error()可以主动抛出异常
* catch一般在最后写
*/
const promise = new Promise((resolve, reject) => {
// resolve('hello')
reject('hello')
})
promise.then(result => {
console.log('读取第一个then', result)
return 'world'
}).catch(result=>{
// 没有错误,不执行
console.log("读取第一个catch", result)
return 'err'
}).then(result=>{
console.log('读取第二个then', result)
})
Promise 的静态方法
/**
* 静态方法
* Promise.resolve() 创建一个立即完成的Promise
* Promise.reject() 创建一个立即拒绝的Promise
* Promise.All() 参数是一个可迭代对象(数组),里面放Promise, 存储的是每个Promise的结果
* 返回的也是一个个Promise对象
* 数组只要有一个Promise拒绝, 就会出错
* Promise.allSettled() 参数是一个可迭代对象(数组),里面放Promise, 存储的是每个Promise的结果
* 无论成功失败都返回结果, 每个结果都放到一个对象里
* 成功: {status: 'fulfilled', value: 3}
* 失败:{status: 'rejected', reason: '出错了'}
* vscode 调试模式需要打断点才能在控制台看到内部数据
* Promise.race() 参数是一个可迭代对象(数组),里面放Promise, 存储的是最快完成的,不论成功失败
* Promise.any() 参数是一个可迭代对象(数组),里面放Promise, 存储的是最快完成的, 只存成功的
* 只有都发生错误, 才会抛出错误, 可以用catch接收
*/
Promise.resolve(1).then(result => console.log(result))
Promise.reject(2).catch(err => console.log(err))
const sum = (a, b) => {
return new Promise(
resolve =>
setTimeout(() => {
resolve(a + b)
}),
3
)
}
// sum(1,2)
// sum(2,3)
// sum(3,4)
Promise.all([sum(1, 2), sum(2, 3), sum(3, 4)]).then(result => {
console.log(result)
})
Promise.all([sum(1, 2), sum(2, 3), Promise.reject('出错了'), sum(3, 4)])
.then(result => {
console.log(result)
})
.catch(err => {
console.log('all遇到拒绝:', err)
})
Promise.allSettled([sum(1, 2), sum(2, 3), Promise.reject('出错了'), sum(3, 4)]).then(result => {
console.log('allSettled:', result)
})
Promise.race([sum(1, 2), sum(2, 3), sum(3, 4), Promise.resolve('立即完成')]).then(result => {
console.log('rece返回最快的:', result)
})
Promise.race([sum(1, 2), sum(2, 3), sum(3, 4), Promise.reject('立即拒绝')]).then(result => {
console.log('race返回最快的:', result)
}).catch(err=>console.log('race遇到拒绝的:',err))
Promise.any([sum(1, 2), sum(2, 3), sum(3, 4)]).then(result => {
console.log('any返回最快的:', result)
})
Promise.any([sum(1,2),Promise.reject('拒绝2')]).then(result => {
console.log('any返回最快的:', result)
}).catch(err=>console.log('any拒绝了的',err))
Promise.any([Promise.reject('拒绝1'),Promise.reject('拒绝2')]).then(result => {
console.log('any返回最快的:', result)
}).catch(err=>console.log('any都拒绝了',err))