272 lines
7.7 KiB
Markdown
272 lines
7.7 KiB
Markdown
# Promise
|
||
|
||
## 进程/线程
|
||
|
||
进程: 独立的工厂, 相互隔离
|
||
|
||
线程: 共享工厂资源的工人, 既可以协作, 也可能互相抢资源
|
||
|
||
| **特性** | **进程** | **线程** |
|
||
| -------- | ---------------- | ----------------- |
|
||
| **资源分配** | 独立的内存空间 | 共享进程的内存空间 |
|
||
| **独立性** | 完全独立,互不影响 | 共享资源,可能相互影响 |
|
||
| **通信方式** | 通过管道、消息队列等 | 直接共享内存 |
|
||
| **开销** | 创建和销毁开销较大 | 创建和销毁开销较小 |
|
||
| **适用场景** | 需要完全隔离的任务(如不同程序) | 需要高效协作的任务(如多任务处理) |
|
||
|
||
## 同步/异步
|
||
|
||
**同步:** 自上而下一行行执行
|
||
|
||
缺点: 会出现阻塞的情况, 一行代码运行慢会阻碍后面代码的执行
|
||
|
||
解决方法: ava/python: 多线程;nodejs: 异步
|
||
|
||
**异步:** 一段代码执行不会影响后面的代码
|
||
|
||
缺点: 无法通过return来设置返回值
|
||
|
||
解决方法: 回调函数
|
||
|
||
新问题: 回调地狱, 可读性差, 难调试
|
||
|
||
解决方法: promise : 一个特殊的容器, 用来存储异步调用的数据
|
||
|
||
## promise
|
||
|
||
### 创建 Promise
|
||
|
||
```js
|
||
/**
|
||
* 创建Promise时, 构造函数需要一个函数作为参数
|
||
* Promise构造函数的回调函数,会在创建Promise时执行,执行时有两个参数传递进去: resolve, reject
|
||
* resolve, reject, 也是两个函数, 通过这两个函数可以向Promise存储数据
|
||
* resolve 在执行正常时存储数据
|
||
* reject 在执行错误时存储数据
|
||
* 读取数据:
|
||
* 通过Promise实例的then方法来获取数据
|
||
* then需要两个回调函数作为参数
|
||
* 通过resolve存储的数据会通过第一个返回
|
||
* 通过reject或者出现异常,会通过第二个返回
|
||
*/
|
||
```
|
||
|
||
```js
|
||
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 的三种状态
|
||
|
||
```js
|
||
/**
|
||
* 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, 则调用第二个回调函数来返回数据
|
||
*/
|
||
```
|
||
|
||
```js
|
||
// 这两种写法是等价的
|
||
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
|
||
|
||
```js
|
||
/**
|
||
* promise
|
||
* then()
|
||
* catch()
|
||
* finally()
|
||
* 这三个方法都是返回一个新的promise
|
||
* then() catch() 返回的Promise会存储回调函数的返回值
|
||
* finally() 的返回值, 不会存储到新的Promise
|
||
*/
|
||
```
|
||
|
||
```js
|
||
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 的链式调用
|
||
|
||
```js
|
||
/**
|
||
* 链式调用,读取的是上一步的执行结果
|
||
* 如果上一步不是想要的, 则跳过当前的方法
|
||
*/
|
||
/**
|
||
* 当promise链式调用中,如果没有catch接收错误, 就会向外抛出
|
||
* throw new Error()可以主动抛出异常
|
||
* catch一般在最后写
|
||
*/
|
||
```
|
||
|
||
```js
|
||
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 的静态方法
|
||
|
||
```js
|
||
/**
|
||
* 静态方法
|
||
* 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接收
|
||
*/
|
||
```
|
||
|
||
```js
|
||
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))
|
||
``` |