ES7之Async/await的使用详解


Posted in Javascript onMarch 28, 2019

在 js 异步请求数据时,通常,我们多采用回调函数的方式解决,但是,如果有多个回调函数嵌套时,代码显得很不优雅,维护成本也相应较高。 ES6 提供的 Promise 方法和 ES7 提供的 Async/Await 语法糖可以更好解决多层回调问题。

Promise 对象用于表示一个异步操作的最终状态(完成或失败),以及其返回的值。
await 操作符用于等待一个Promise 对象。它只能在异步函数 async function 中使用。
await 表达式会暂停当前 async function 的执行,等待 Promise 处理完成。若 Promise 正常处理(fulfilled),其回调的resolve函数参数作为 await 表达式的值,继续执行 async function。

一个ajax请求时

通常 使用 ajax 请求数据时,会

$.ajax({
 url: 'data1.json',
 type: 'GET',
 success: function (res) {
  console.log(res) // 请求成功,则得到结果res
 },
 error: function(err) {
  console.log(err)
 }
})

上面可以得到我们想要的结果 res ---> { "url": "data2.json" }

多个ajax请求时

但是 当得到的数据 res 需要用于另一个 ajax 请求时,则需要如下写法:

$.ajax({
 url: 'data1.json',
 type: 'GET',
 success: function (res) {
  $.ajax({
   url: res.url, // 将 第一个ajax请求成功得到的res 用于第二个ajax请求
   type: 'GET',
   success: function (res) {
    $.ajax({
     url: res.url, // 将第二个ajax请求成功得到的res 用于第三个ajax请求
     type: 'GET',
     success: function (res) {
      console.log(res) // {url: "this is data3.json"}
     },
     error: function(err) {
      console.log(err)
     }
    })
   },
   error: function(err) {
    console.log(err)
   }
  })
 },
 error: function(err) {
  console.log(err)
 }
})

上面出现多个回调函数的嵌套,可读性较差(虽然这种嵌套在平常的开发中少见,但是在node服务端开发时,还是很常见的)

优化方法

使用 promise 链式操作

如下,使用 Promise,进行链式操作,可以使上面的异步代码看起来如同步般易读,从回调地狱中解脱出来。。

function ajaxGet (url) {
 return new Promise(function (resolve, reject) {
  $.ajax({
   url: url,
   type: 'GET',
   success: function (res) {
    resolve(res);
   },
   error: function(err) {
    reject('请求失败');
   }
  })
 })
};

ajaxGet('data1.json').then((d) => {
 console.log(d);  // {url: "data2.json"}
 return ajaxGet(d.url);
}).then((d) => {
 console.log(d);  // {url: "data3.json"}
 return ajaxGet(d.url);
}).then((d) => {
 console.log(d);  // {url: "this is data3.json"}
})

Async/await 方法

  • async 表示这是一个async函数,即异步函数,await只能用在这个函数里面。
  • await 表示在这里等待promise返回结果了,再继续执行。
  • await 后面跟着的应该是一个promise对象(当然,其他返回值也没关系,只是会立即执行,不过那样就没有意义了…)
  • await 操作符用于等待一个Promise 对象。它只能在异步函数 async function 中使用。
  • await 等待的虽然是promise对象,但不必写.then(..),直接可以得到返回值。

执行一个ajax请求,可以通过如下方法:

function ajaxGet (url) {
 return new Promise(function (resolve, reject) {
  $.ajax({
   url: url,
   type: 'GET',
   success: function (res) {
    resolve(res)
   },
   error: function(err) {
    reject('请求失败')
   }
  })
 })
};

async function getDate() {
 console.log('开始')
 let result1 = await ajaxGet('data1.json');
 console.log('result1 ---> ', result1); // result1 ---> {url: "data2.json"}
};
getDate();  // 需要执行异步函数

执行多个ajax请求时:

function ajaxGet (url) {
 return new Promise(function (resolve, reject) {
  $.ajax({
   url: url,
   type: 'GET',
   success: function (res) {
    resolve(res)
   },
   error: function(err) {
    reject('请求失败')
   }
  })
 })
};

async function getDate() {
 console.log('开始')
 let result1 = await ajaxGet('data1.json');
 let result2 = await ajaxGet(result1.url);
 let result3 = await ajaxGet(result2.url);
 console.log('result1 ---> ', result1); // result1 ---> {url: "data2.json"}
 console.log('result2 ---> ', result2); // result2 ---> {url: "data3.json"}
 console.log('result3 ---> ', result3); // result3 ---> {url: "this is data3.json"}
};

getDate(); // 需要执行异步函数

async await捕捉错误:

async await中.then(..)不用写了,那么.catch(..)也不用写,可以直接用标准的try catch语法捕捉错误。

例如,如果下面的 url 写错了

function ajaxGet (url) {
 return new Promise(function (resolve, reject) {
  $.ajax({
   url: url111, // 此处为错误的 url
   type: 'GET',
   success: function (res) {
    resolve(res)
   },
   error: function(err) {
    reject('请求失败')
   }
  })
 })
};


async function getDate() {
 console.log('开始')
 try {
  let result1 = await ajaxGet('data1.json'); // 执行到这里报错,直接跳至下面 catch() 语句
  let result2 = await ajaxGet(result1.url);
  let result3 = await ajaxGet(result2.url);
  console.log('result1 ---> ', result1);
  console.log('result2 ---> ', result2);
  console.log('result3 ---> ', result3);

 } catch(err) {
  console.log(err) // ReferenceError: url111 is not defined
 }
};

getDate(); // 需要执行异步函数

源码

源码查看

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
一个很简单的jquery+xml+ajax的无刷新树结构(无css,后台是c#)
Jun 02 Javascript
JavaScript极简入门教程(二):对象和函数
Oct 25 Javascript
jQuery焦点控制图层展示延迟隐藏的方法
Mar 09 Javascript
Bootstrap中的Panel和Table全面解析
Jun 13 Javascript
vue.js 获取当前自定义属性值
Jun 01 Javascript
详解Vue学习笔记入门篇之组件的内容分发(slot)
Jul 17 Javascript
vuex 的简单使用
Mar 22 Javascript
微信小程序生成分享海报方法(附带二维码生成)
Mar 29 Javascript
在layui.use 中自定义 function 的正确方法
Sep 16 Javascript
angular8和ngrx8结合使用的步骤介绍
Dec 01 Javascript
Vue中this.$nextTick的作用及用法
Feb 04 Javascript
vue 实现在同一界面实现组件的动态添加和删除功能
Jun 16 Javascript
详解vue-cli3多环境打包配置
Mar 28 #Javascript
微信小程序之onLaunch与onload异步问题详解
Mar 28 #Javascript
详解vue使用插槽分发内容slot的用法
Mar 28 #Javascript
详解一个基于套接字实现长连接的express
Mar 28 #Javascript
微信小程序学习笔记之跳转页面、传递参数获得数据操作图文详解
Mar 28 #Javascript
微信小程序学习笔记之表单提交与PHP后台数据交互处理图文详解
Mar 28 #Javascript
深入理解es6块级作用域的使用
Mar 28 #Javascript
You might like
php使用正则过滤js脚本代码实例
2014/05/10 PHP
PHP动态编译出现Cannot find autoconf的解决方法
2014/11/05 PHP
PHP中让curl支持sock5的代码实例
2015/01/21 PHP
支持中文的PHP按字符串长度分割成数组代码
2015/05/17 PHP
禁止拷贝网页内容的js代码
2014/01/22 Javascript
在Linux上用forever实现Node.js项目自启动
2014/07/09 Javascript
javascript用正则表达式过滤空格的实现代码
2016/06/14 Javascript
基于jQuery实现火焰灯效果导航菜单
2017/01/04 Javascript
js绑定事件和解绑事件
2017/04/27 Javascript
微信小程序使用slider设置数据值及switch开关组件功能【附源码下载】
2017/12/09 Javascript
GOJS+VUE实现流程图效果
2018/12/01 Javascript
vue之延时刷新实例
2019/11/14 Javascript
JavaScript实现电灯开关小案例
2020/03/30 Javascript
解决antd 表单设置默认值initialValue后验证失效的问题
2020/11/02 Javascript
[00:36]DOTA2上海特级锦标赛 Alliance战队宣传片
2016/03/04 DOTA
python网络编程学习笔记(五):socket的一些补充
2014/06/09 Python
Python struct模块解析
2014/06/12 Python
Python安装官方whl包和tar.gz包的方法(推荐)
2017/06/04 Python
python中hashlib模块用法示例
2017/10/30 Python
如何利用Python分析出微信朋友男女统计图
2019/01/25 Python
对django中foreignkey的简单使用详解
2019/07/28 Python
Python+Pyqt实现简单GUI电子时钟
2021/02/22 Python
python爬虫泛滥的解决方法详解
2020/11/25 Python
html5+svg学习指南之SVG基础知识
2014/12/17 HTML / CSS
最新大学生自我评价
2013/09/24 职场文书
中专自我鉴定范文
2013/10/16 职场文书
竞聘上岗演讲稿范文
2014/01/10 职场文书
小学中秋节活动方案
2014/02/06 职场文书
《姥姥的剪纸》教学反思
2014/02/25 职场文书
妈妈活动方案
2014/08/15 职场文书
考研复习计划
2015/01/19 职场文书
同意报考公务员证明
2015/06/17 职场文书
Spring Boot 整合 Apache Dubbo的示例代码
2021/07/04 Java/Android
 Redis 串行生成顺序编码的方法实现
2022/04/03 Redis
hive数据仓库新增字段方法
2022/06/25 数据库
Windows Server 2008配置防火墙策略详解
2022/06/28 Servers