问题引入
ES6以前,如果我们想要保证一段代码(主要是保证异步代码,如ajax请求)的执行顺序,需要书写多层嵌套的函数,如
想要让函数的执行顺序保证为 ajax1() -> ajax2() -> ajax3()
*只是展示概念,并非真实可运行的代码*
ajax1(){
xxx
return ajax2(){
xxx
return ajax3(){
xxx
}
}
}
由多层的回调函数嵌套而成,虽然能实现功能
但是,很显然代码 难以维护 耦合性差 可读性差
使用Promise可以解决这样的问题
什么是Promise
promise 是一个对象,保存了未来才会结束的事件
promise对象 是 由Promise(function())【注意P是大写的】构造函数 创建出的 实例 如 const pro = new Promise()
其中 pro 就是被创建出的promise对象实例
promise是怎么起作用的?
- 要使用promise,首先应该通过构造函数创建一个promise实例
- 在构造函数中传入一个函数,它有两个参数,resolve和reject,他们都是方法
- resolve()方法的调用表示promise对象的状态从 未完成 到 完成
- reject()方法的调用表示promise对象的状从 未完成 到 失败
- 要注意的是promise在声明时,其构造函数传入的方法会 立即调用
- 使用 then() 方法来指定 resolve和reject的回调函数;这一回调函数将在当前所有同步任务执行完后才会执行
- then()方法有两个方法参数,分别对应promise中执行resolve和reject的回调方法,而这两个方法的参数,就是在执行resolve或者reject时向他们传入的数据,如then中第一个msg的值就是"success"
const pro = new Promise(function(resolve,reject){
let stat = 0;
if (stat === 1){
resolve("success");
}else{
reject("error")
}
})
pro.then((msg)=> {console.log(msg)},(msg)=> {onsole.log(msg)})
// stat = 1->success
// stat = 0->error
promise的这些特性,已经可以帮助我们确定js代码的执行顺序了
在某个promise对象的后面调用then,那么then中的方法必然会在promise的状态转变为 “完成” 后再调用(必须让promise中的方法执行完了后才轮得到then执行),然后我们再在then中返回下一个要执行的方法(通常是异步方法,并且这一方法会返回promise对象),以此类推执行,形成了then的链式调用
示例,thenFs是一个异步的文件读取模块,它的一些操作如(readFile:会把文件读取的内容作为resolve的参数返回[这样你在then中就可以获取到文件内容]
在上述案例中,我们通过对 thenFs.readFile() 产生的 promise对象进行.then操作,获取了它的返回值,再在.then中 调用并返回 了下一个thenFs.readFile()产生的promise对象,在下一个.then又获取了它的值,以此类推不断调用,最终保证了代码的执行顺序 promise还有一些其他的方法,如.catch捕获错误,Promise.race()和Promise.all()等,这里不再赘述
虽然我们已经通过 .then的链式调用 实现了代码的顺序执行,但是上述的代码仍然让人觉得复杂,冗余,难以理解
可以通过async和await来使得代码结构更加清晰
async和await
await 可以修饰某个 返回Promise对象 的方法,修饰后的值不再是Promise实例了,而是一个 真正的值 如果方法内部用到了await,那么要在该方法前加async
import thenFs from 'then-fs'
//使用async和await来进行异步调用
async function getAllFile(){
const a1 = await thenFs.readFile('./1.txt','utf8')
const a2 = await thenFs.readFile('./2.txt','utf8')
const a3 = await thenFs.readFile('./3.txt','utf8')
console.log(a1);
console.log(a2);
console.log(a3);
}
getAllFile();
使用了async和await之后,我们在函数getAllFile中获取了三个 由thenFs.readFile产生的promise对象的 值 此时想要什么执行顺序就可以写什么执行顺序了,如案例中必然是输出a1,a2,a3的内容
-
注意,async 和 await必须对应出现,不能单独使用
-
注意,在async和 第一个await 之间的代码 会同步执行,第一个await之后的代码会异步执行
如下面代码的执行顺序是abdc
console.log("a");
async function getAllFile(){
console.log("b");
const a1 = await thenFs.readFile('./1.txt','utf8')
const a2 = await thenFs.readFile('./2.txt','utf8')
const a3 = await thenFs.readFile('./3.txt','utf8')
console.log("c");
}
getAllFile();
console.log("d");
//a,b,d,c