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 相关文章推荐
js实现点击注册按钮开始读秒倒计时的小例子
May 11 Javascript
jQuery 实现自动填充邮箱功能(带下拉提示)
Oct 14 Javascript
js实现可控制左右方向的无缝滚动效果
May 29 Javascript
JS去除空格和换行的正则表达式(推荐)
Jun 14 Javascript
IE下JS保存图片的简单实例
Jul 15 Javascript
jQuery层次选择器用法示例
Sep 09 Javascript
jQuery EasyUI 右键菜单--关闭标签/选项卡的简单实例
Oct 10 Javascript
Javascript中的getter和setter初识
Aug 17 Javascript
AngularJS实现的简单拖拽功能示例
Jan 02 Javascript
vue中简单弹框dialog的实现方法
Feb 26 Javascript
纯js封装的ajax功能函数与用法示例
May 14 Javascript
mocha的时序规则讲解
Feb 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函数)
2006/10/09 PHP
Ajax+PHP 边学边练 之二 实例
2009/11/24 PHP
php商品对比功能代码分享
2015/09/24 PHP
Thinkphp3.2.3整合phpqrcode生成带logo的二维码
2016/07/21 PHP
Javascript & DHTML 实例编程(教程)DOM基础和基本API
2007/06/02 Javascript
jquery ajax请求实例深入解析
2012/11/26 Javascript
jquery $.fn $.fx是什么意思有什么用
2013/11/04 Javascript
JavaScript每天定时更换皮肤样式的方法
2015/07/01 Javascript
JavaScript事件学习小结(三)js事件对象
2016/06/09 Javascript
AngularJS 与百度地图的结合实例
2016/10/20 Javascript
微信小程序 数组(增,删,改,查)等操作实例详解
2017/01/05 Javascript
微信小程序 蓝牙的实现实例代码
2017/06/27 Javascript
jQuery中过滤器的基本用法示例
2017/10/11 jQuery
使用 Node.js 模拟滑动拼图验证码操作的示例代码
2017/11/02 Javascript
JS实现获取word文档内容并输出显示到html页面示例
2018/06/23 Javascript
在axios中使用params传参的时候传入数组的方法
2018/09/25 Javascript
基于vue如何发布一个npm包的方法步骤
2019/05/15 Javascript
vue调用语音播放的方法
2019/09/27 Javascript
JS+CSS实现3D切割轮播图
2020/03/21 Javascript
python根据日期返回星期几的方法
2015/07/06 Python
Flask框架实现给视图函数增加装饰器操作示例
2018/07/16 Python
windows下pycharm安装、创建文件、配置默认模板
2018/07/31 Python
python实现五子棋游戏
2019/06/18 Python
如何基于python操作json文件获取内容
2019/12/24 Python
后端开发使用pycharm的技巧(推荐)
2020/03/27 Python
Python如何爬取qq音乐歌词到本地
2020/06/01 Python
python创建文本文件的简单方法
2020/08/30 Python
python 装饰器重要在哪
2021/02/14 Python
Pat McGrath Labs官网:世界上最有影响力的化妆师推出的彩妆品牌
2018/01/07 全球购物
法国购买隐形眼镜和眼镜网站:Optical Center
2019/10/08 全球购物
什么是数据库锁?Oracle中都有哪些类型的锁?
2015/08/21 面试题
黄河象教学反思
2014/02/10 职场文书
竞聘演讲稿
2014/04/24 职场文书
社区维稳工作方案
2014/06/06 职场文书
如何自己动手写SQL执行引擎
2021/06/02 MySQL
MongoDB修改oplog大小的四种方法
2022/04/11 MongoDB