javascript异步:callback-promise-async/await

2022年10月7日08:15:24

JS三座大山:原型原型链、作用域闭包、同步异步。

一、相关概念

首先我们先了解同步、异步阻塞、非阻塞等四个概念;

1、异步和同步

  • 同步和异步强调的是消息通信机制 (synchronous communication/ asynchronous communication)
  • 同步是指:当程序1调用程序2时,程序1停下不动,直到程序2完成回到程序1来,程序1才继续执行下去。
  • 异步是指:当程序1调用程序2时,程序1径自继续自己的下一个动作,不受程序2的的影响。

2、阻塞和非阻塞

  • 阻塞和非阻塞强调的是程序在等待调用结果(消息,返回值)时的状态.
  • 阻塞调用是指调用结果返回之前,当前线程会被挂起。调用线程只有在得到结果之后才会返回。
  • 非阻塞调用指在不能立刻得到结果之前,该调用不会阻塞当前线程。

二、callback

例子:

functionfoo(callback){//定义函数的时候将另一个函数(回调函数)作为参数传入定义的函数中。$ajax({//...
        success:callback//异步操作执行完毕后,再执行该回调函数,确保回调在异步操作之后执行。});}functionmyCallback(result){//...}foo(myCallback);

关于回调函数可以参考我的另外一篇博客:JavaScript同步回调和异步回调(个人理解)

三、Promise

1.Promise含义

Promise 是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大。它由社区最早提出和实现,ES6 将其写进了语言标准,统一了用法,原生提供了Promise对象。

所谓Promise,简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。从语法上说,Promise 是一个对象,从它可以获取异步操作的消息。Promise 提供统一的 API,各种异步操作都可以用同样的方法进行处理。

2.基本用法

  • 例子
functionf1(data){returnnewPromise(function(resolve, reject){if(data===1){resolve('sucess')}else{reject('faile')}});}f1(1).then(function(result){
  console.log(result)})//输出sucess
  • (1)对象的状态不受外界影响。Promise对象代表一个异步操作,有三种状态:pending(进行中)、fulfilled(已成功)和rejected(已失败)。只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。这也是Promise这个名字的由来,它的英语意思就是“承诺”,表示其他手段无法改变。

  • (2)一旦状态改变,就不会再变,任何时候都可以得到这个结果。Promise对象的状态改变,只有两种可能:从pending变为fulfilled和从pending变为rejected。只要这两种情况发生,状态就凝固了,不会再变了,会一直保持这个结果,这时就称为 resolved(已定型)。如果改变已经发生了,你再对Promise对象添加回调函数,也会立即得到这个结果。这与事件(Event)完全不同,事件的特点是,如果你错过了它,再去监听,是得不到结果的。

3、Promise异步(demo实例)

例子1

// 故意把f1函数写错(data写错成dat)functionf1(dat){returnnewPromise(function(resolve, reject){if(data===1){resolve('sucess')}else{reject('faile')}});}functionf2(data){returnnewPromise(function(resolve, reject){if(data===1){resolve('sucess')}else{reject('faile')}});}f1(1).then(function(result){
  console.log(result)}).catch(function(error){ console.log(error)});f2(2).then(function(result){
  console.log(result)}).catch(function(error){ console.log(error)});
  • 输出如下图,可以看到,即使f1出错了,f2也输出了函数的结果

javascript异步:callback-promise-async/await

3、Promise.all

Promise.all()方法用于将多个 Promise 实例,包装成一个新的 Promise 实例。

  • 只有Promise.all()中多个实例的状态都变成fulfilled,或者其中有一个变为rejected,才会调用Promise.all方法后面的回调函数。
functionf1(data){returnnewPromise(function(resolve, reject){if(data===1){resolve('sucess-1')}else{reject('faile-1')}});}functionf2(data){returnnewPromise(function(resolve, reject){if(data===1){resolve('sucess-2')}else{reject('faile-2')}});}
Promise.all([f1(1),f2(2)]).then(function(result){
    console.log(result)}).catch(function(error){ 
    console.log(error)});// faile-2

四、Async\await

Async\await和Promise一样是非阻塞的,Async 的价值在于用写同步的方式写异步,1避免了阻塞,2必免写回调

1、含义

ES2017 标准引入了 async 函数,使得异步操作变得更加方便。

async 函数是什么?一句话,它就是 Generator 函数的语法糖。(这是阮一峰说的,不是太明白,generate函数在此不展开,后期研究清楚后再讲)

  • async:定义异步函数
    1)自动把函数转换为Promise
    2)当调用异步函数时,函数返回值会被resolve处理
    3)异步函数内部可以使用await

  • await:暂停异步函数的执行
    1)当使用在Promise前面时,await等待Promise完成,并返回Promise的resolve的结果
    2)await只能和Promise一起使用,不能和callback一起使用
    3)await只能用在async函数中

2、用法

async 函数返回一个 Promise 对象,promise 返回的 resolve 对象可能用 await 去接,但是 reject 无法用 await 接收到,所以要用 try catch 去处理。(当然还有Promise运行过程中的错误,也可以catch到)

2.0、await\async

async:自动把函数转换为Promise;所以,此处的async function f1(), 和2.1中的**return new Promise()**是一样的;

asyncfunctionf1(data){if(data===1){
        console.log('sucess-1')return'sucess-1'}else{
        console.log('faile-1')return'faile-1'}}asyncfunctionf3(){var f11=awaitf1(1);
    console.log(f11+'main')}f3()// sucess-1// sucess-1main

2.1、await-resolve

以下demo正常运行;

  • 例子1
functionf1(data){returnnewPromise(function(resolve, reject){if(data===1){
      console.log('sucess-1')resolve('sucess-1')}else{
      console.log('faile-1')reject('faile-1')}});}asyncfunctionf3(){var f11=awaitf1(1);
  console.log(f11+'main')}f3()// sucess-1// sucess-1main

把上面例子输入改为2,可以看到f11并没有收到返回值;并且代码报错了

  • 例子2
functionf1(data){returnnewPromise(function(resolve, reject){if(data===1){
      console.log('sucess-1')resolve('sucess-1')}else{
      console.log('faile-1')reject('faile-1')}});}asyncfunctionf3(){var f11=awaitf1(2);
  console.log(f11+'main')}f3()

错误信息如下
javascript异步:callback-promise-async/await

2.3、reject-then/catch

用catch接收Promise中的错误,await接收resolve,

  • 例子3(外层catch错误)
    then接收返回值,catch捕捉Promise中reject的错误,和运行中的错误;
functionf1(data){returnnewPromise(function(resolve, reject){if(data===1){
      console.log('sucess-1')resolve('sucess-1')}else{
      console.log('faile-1')reject('faile-1')}});}asyncfunctionf3(){var f11=awaitf1(2);
  console.log(f11+'main')}f3().then(function(result){
    console.log(result)}).catch(error=>{
    console.log(error+'catch')})// faile-1// faile-1catch

2.4、reject-try/catch

  • 例子4:
    直接在await的外层使用try/catch(即async里面catch错误)
functionf1(data){returnnewPromise(function(resolve, reject){if(data===1){
      console.log('sucess-1')resolve('sucess-1')}else{
      console.log('faile-1')reject('faile-1')}});}asyncfunctionf3(){try{var f11=awaitf1(2);}catch(error){
    console.log(error+'try/catch')};
  console.log(f11+'main')}f3()// faile-1// faile-1try/catch// undefinedmain

参考

【1】同步(Synchronous)和异步(Asynchronous)
【2】同步和异步的概念
【3】JS 异步(callback→Promise→async/await)
【4】阮一峰-Promise 对象
【5】阮一峰-async 函数的含义和用法

  • 作者:junxuezheng
  • 原文链接:https://blog.csdn.net/junxuezheng/article/details/109248431
    更新时间:2022年10月7日08:15:24 ,共 4897 字。