promise、async和await之执行顺序的那点事
首先在控制台测试以下代码
async function async1(){ console.log('2: async1 start') await async2() console.log('6: async1 end') } async function async2(){ console.log('3: async2') } console.log('1: script start') setTimeout(function(){ console.log('8: setTimeout') },0) async1(); new Promise(function(resolve){ console.log('4: promise1') resolve(); }).then(function(){ console.log('7: promise2') }) console.log('5: script end')
果然,实践才是检验真理的唯一标准。运行的结果与原文说的不一样。
小结一下理解的概念:
1、如果在函数定义时,在function前面加上async ,那么在调用它以后,会返回一个 Promise 对象(还是阮一峰老师说的精辟),如上面的async1()。
当执行async1时,一旦遇到其中的 await 就会先返回,等到触发的异步操作async2完成,再接着执行async1函数体内后面的语句。
2、Promise是一个立即执行函数。如上面编号为2、3、4的都是立即输出,排在编号5之前。
上述代码我在console中执行多次顺序不变。将setTimeout的延时时间由0改为3000也一样。
如何让编号7的语句在最后执行呢?办法是将代码中的resolve()也用setTimeout()包起来,并设置延时为3000来查看效果。
什么是Async/Await?
async搭配await是ES7提出的,它的实现是基于Promise。
- async/await是写异步代码的新方式,以前的方法有回调函数和Promise。
- async/await是基于Promise实现的,它不能用于普通的回调函数。
- async/await与Promise一样,是非阻塞的。
- async/await使得异步代码看起来像同步代码,这正是它的魔力所在。
当然,如果不理解Promise的概念,可能对上面的内容还是不明白。
所以,下面简单说一下Promise的概念
Promise是异步编程的一种解决方案,我理解是为了解决js中的回调地狱问题,让代码更清晰。
ES6规定,Promise对象是一个构造函数,用来生成Promise实例
var promise = new Promise(function(resolve, reject) { // ... some code if (/* 异步操作成功 */){ resolve(value); } else { reject(error); } });
Promise实例具有then方法,也就是说,then方法是定义在原型对象Promise.prototype上的。
它的作用是为Promise实例添加状态改变时的回调函数。then方法的第一个参数是Resolved状态的回调函数,第二个参数(可选)是Rejected状态的回调函数。
new出来的Promise会保持一个pending状态,当异步操作完成(通常如访问网址获取数据),相应地调用resolve或reject;Promise的状态由pending相应变更为fulfilled [实现] 或rejected[被否决] ,并且
1 当promise 状态发生改变,就会触发.then()里的相应函数处理后续步骤
2 promise 状态一经改变,不会再变
then方法返回的是一个新的Promise实例(注意,不是原来那个Promise实例)。因此可以采用链式写法,即then方法后面再调用另一个then方法。
注意,Promise.reject()
方法的参数,会原封不动地作为reject
的理由,变成后续方法的参数。这一点与Promise.resolve
方法不一致。
要区分几个概念,第一,reject是用来抛出异常的,catch是用来处理异常的;第二:reject是Promise的方法,而then和catch是Promise实例的方法(Promise.prototype.then 和 Promise.prototype.catch)。
catch只是一个语法糖而己 还是通过then 来处理的
then的第二个参数和catch捕获错误信息的时候会就近原则,如果是promise内部报错,reject抛出错误后,then的第二个参数和catch方法都存在的情况下,只有then的第二个参数能捕获到,如果then的第二个参数不存在,则catch方法会捕获到。
建议总是使用catch方法,而不使用then方法的第二个参数。理由是第二种写法可以捕获前面then方法执行中的错误,也更接近同步的写法(try/catch)。
算了,感觉还是一头雾水。平时知道对new出来的promise对象连续调用then方法就好了,就像本文开头的代码或下面的代码:
new Promise(function(resolve, reject) { setTimeout(() => resolve(1), 1000); }).then(function(result) { alert(result); // 1 return new Promise((resolve, reject) => { // (*) setTimeout(() => resolve(result * 2), 1000); }); }).then(function(result) { // (**) alert(result); // 2 return new Promise((resolve, reject) => { setTimeout(() => resolve(result * 2), 1000); }); }).then(function(result) { alert(result); // 4 });
参考:https://segmentfault.com/a/1190000015057278
https://www.jianshu.com/p/79c9e6c961cd
https://blog.csdn.net/weixin_42470791/article/details/82560734
https://www.cnblogs.com/pu369/p/12523361.html