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。

注意:await函数不能单独使用,而且async函数返回的是一个Promise对象,可以使用then函数添加回调函数。当函数执行的时候,一旦遇到await函数就会先返回一个Promise对象,等到异步操作完成,再去执行后面的语句。如果 await 后面的异步操作出错,那么等同于 async 函数返回的 Promise 对象被 reject!
  • 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/gogo_steven/article/details/103352762?depth_1-utm_source=distribute.pc_relevant.none-task&utm_source=distribute.pc_relevant.none-task

https://blog.csdn.net/ligen52/article/details/82187682?depth_1-utm_source=distribute.pc_relevant.none-task&utm_source=distribute.pc_relevant.none-task

https://blog.csdn.net/weixin_42470791/article/details/82560734

https://www.cnblogs.com/pu369/p/12523361.html

posted @ 2020-11-04 11:37  进击的乌龟  阅读(452)  评论(0编辑  收藏  举报