Promise异步编程的应用
Promise出现的原因或者它的出现为了解决什么问题
在Promise出现之前,解决异步问题的方式通常是用回调函数的方式来解决的,看下面几个例子:
// fs文件操作 第二个参数为指定的回调函数
require('fs').readFile('./index.html',(err,data)=>{})
// AJAX 第三个参数为指定的回调函数
$.get('/server',{},data=>{})
// 定时器相关 第一个参数就是指定的回调函数
setTimeout(()=>{},1000)
那回调函数的方式就可以解决异步的问题,那为什么还要使用Promise呢,下面是传统的回调函数方法解决异步的缺点:
1、可读性差(回调地狱):回调地狱的代码嵌套深度高,导致代码难以理解和阅读。每个异步操作的回调函数需要嵌套在前一个异步操作的回调函数中,使得代码结构变得复杂。
2、错误处理困难:在回调地狱中,错误处理通常需要在每个回调函数中进行,容易出现遗漏或混乱。当出现错误时,追踪和调试问题变得困难,尤其是当错误处理代码也被嵌套在多个层级中时。
3、难以维护:由于代码结构复杂,回调地狱中的代码修改和维护都会变得困难。如果需要添加、修改或删除某个异步操作,可能需要修改多个嵌套的回调函数,增加了代码的脆弱性。
4、缺乏顺序控制:在回调地狱中,异步操作的执行顺序通常由回调函数的嵌套关系决定,使得代码的执行流程不易理解和控制。特别是在有多个异步操作需要按特定顺序执行的情况下,代码会变得混乱。
使用Promise就可以解决上面的问题,下面展开Promise相关的内容.
对于一个Promise来说,他有两个内置属性,分别为:PromiseState与PromiseResult。
- PromiseState:表示 Promise 的当前状态,它可以有以下三个可能的取值:
“pending”:Promise 正在进行中,尚未完成或被拒绝。
“fulfilled”:Promise 已成功完成,即已被解析。
“rejected”:Promise 被拒绝,即出现了错误或异常。 - PromiseResult:表示 Promise 的最终结果值,它的值取决于 Promise 的状态。如果 Promise 被成功解析(fulfilled),则该属性将包含解析后的值。如果 Promise 被拒绝(rejected),则该属性将包含拒绝的原因。
还有一点就是一个Promise实例的状态只能改变一次,且只能从Pending到fulfilled或者从Pending到rejected。
Promise的工作流程![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/53b15cd0b83d153c3318d1f492f98214.png)
Promise的构造函数的组成
Promise(executor){}
- executor函数:执行器函数 (resolve,reject)=>{]
- resolve函数:内部定义成功时我们调用的函数
- reject()函数:内部定义失败时我们调用的函数
注:executor执行器函数是同步调用的,如下例:
new Promise((resolve,reject)=>{
console.log(1)
})
console.log(2)
运行结果:
Promise.resolve()
对于这个静态方法,如果传入的参数是一个非 Promise 对象(比如一个普通的值或一个 对象),那么返回的 Promise 对象将会处于已解决(fulfilled)状态,并且它的值将是传入的参数。
如果传入的参数是一个 Promise 对象,那么 Promise.resolve 方法将直接返回这个 Promise 对象,则返回的 Promise 对象的状态就是内部这个promise的状态,
看代码:
const p = Promise.resolve(new Promise((resolve,reject)=>{
reject(2)
}))
console.log(p)
输出结果如下:
Promise.reject()
对于这个方法,无论传入的参数是什么,Promise.reject 方法返回的 Promise 对象都将处于已拒绝(rejected)状态。传入的参数将成为拒绝原因,可以通过 Promise 对象的 catch 方法或 onRejected 回调函数来处理。
Promise.all()
Promise.all 方法是一个静态方法,用于处理多个 Promise 对象,并返回一个新的 Promise 对象。它接受一个可迭代的对象(比如数组)作为参数,该可迭代对象包含了多个 Promise 对象。
如果传入的可迭代对象是空的,则 Promise.all 立即返回一个已解决(fulfilled)状态的 Promise 对象,且该 Promise 对象的值是一个空数组 []。
console.log(Promise.all([]))
如果传入的可迭代对象中的所有 Promise 对象都处于已解决状态,则 Promise.all 返回的 Promise 对象也会处于已解决状态,并且它的值是一个与传入的 Promise 对象顺序相对应的值数组。
如果传入的可迭代对象中的任何一个 Promise 对象处于已拒绝状态,则 Promise.all 返回的 Promise 对象会立即处于已拒绝状态,并且它的拒绝原因是第一个被拒绝的 Promise 对象的拒绝原因。
const p1 = Promise.resolve(1)
const p2 = Promise.resolve(2)
const p3 = Promise.resolve(3)
Promise.all([p1,p2,p3]).then(res=>{
console.log(res) //[1,2,3]
})
console.log(Promise.all([p1,p2,p3]))
下面是运行结果:
当其中有reject的promise时又是怎样的呢,看下面的例子:
const p1 = Promise.resolve(1)
const p2 = Promise.reject(2)
const p3 = Promise.reject(3)
console.log(Promise.all([p1,p2,p3]))
可以看到它的拒绝原因是第一个被拒绝的 Promise 对象的拒绝原因。
Promise.race()
Promise.race 方法是一个静态方法,用于处理多个 Promise 对象,并返回一个新的 Promise 对象。它接受一个可迭代的对象(比如数组)作为参数,该可迭代对象包含了多个 Promise 对象。
Promise.race 方法的行为如下:
如果传入的可迭代对象是空的,则 Promise.race 返回的 Promise 对象将永远处于待定(pending)状态。
console.log(Promise.race([]))
运行结果:
如果传入的可迭代对象中的任何一个 Promise 对象首先变为已解决(fulfilled)或已拒绝(rejected)状态,则 Promise.race 返回的 Promise 对象也会立即变为相应的状态,并且其值或拒绝原因与首先完成的 Promise 对象相对应。
const p1 = Promise.reject(1)
const p2 = Promise.resolve(2)
const p3 = Promise.reject(3)
console.log(Promise.race([p1,p2,p3]))
改变Promise实例状态的方式
- resolve 将状态变成fulfilled
- reject 将状态变成rejected
- throw 将状态变成rejected
Promise指定多个回调
const p1 = Promise.reject(1)
p1.catch(()=>{
console.log(12)
})
p1.catch(()=>{
console.log(34)
})
运行结果:
指定多个then也是同理的,都会执行(前提是promise的状态发生了变化,如果一直是pending状态就都不会执行)。
中断Promise链的方式
运行结果只会输出1和2,不会输出3,因为我们把它中断了,并且中断promise链的方式有且只有这一种。