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 (八) 插播:jQuery实施方案
Feb 23 Javascript
用unescape反编码得出汉字示例
Apr 24 Javascript
wap图片滚动特效无css3元素纯js脚本编写
Aug 22 Javascript
javascript函数特点实例分析
May 14 Javascript
表单input项使用label同时引用Bootstrap库导致input点击效果区增大问题
Oct 11 Javascript
Angular.js实现多个checkbox只能选择一个的方法示例
Feb 24 Javascript
vue2.0父子组件间通信的实现方法
Apr 19 Javascript
jquery仿微信聊天界面
May 06 jQuery
在vue中使用vue-echarts-v3的实例代码
Sep 13 Javascript
vue-cli设置css不生效的解决方法
Feb 07 Javascript
javascript实现简单留言板案例
Feb 09 Javascript
vue使用refs获取嵌套组件中的值过程
Mar 31 Vue.js
详解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数据库类
2009/05/27 PHP
一个PHP验证码类代码分享(已封装成类)
2011/07/17 PHP
PHP获取photoshop写入图片文字信息的方法
2015/03/31 PHP
PHP巧妙利用位运算实现网站权限管理的方法
2017/03/12 PHP
PHP后端银联支付及退款实例代码
2017/06/23 PHP
PHP simplexml_load_string()函数实例讲解
2019/02/03 PHP
php curl简单采集图片生成base64编码(并附curl函数参数说明)
2019/02/15 PHP
javascript基础的动画教程,直观易懂
2007/01/10 Javascript
科讯商业版中用到的ajax空间与分页函数
2007/09/02 Javascript
javascript中获取下个月一号,是星期几
2012/06/01 Javascript
jquery插件实现鼠标经过图片右侧显示大图的效果(类似淘宝)
2013/02/04 Javascript
javascript中直接写php代码的方法
2013/07/31 Javascript
html文件中jquery与velocity变量中的$冲突的解决方法
2013/11/01 Javascript
浅谈jquery回调函数callback的使用
2015/01/30 Javascript
JS获取月份最后天数、最大天数与某日周数的方法
2015/12/08 Javascript
ASP.NET jquery ajax传递参数的实例
2016/11/02 Javascript
JS定时器实现数值从0到10来回变化
2016/12/09 Javascript
js模拟F11页面全屏显示
2019/09/17 Javascript
Vue中keep-alive组件的深入理解
2020/08/23 Javascript
Python实现在线音乐播放器
2017/03/03 Python
Python3 合并二叉树的实现
2019/09/30 Python
pytorch的梯度计算以及backward方法详解
2020/01/10 Python
python zip,lambda,map函数代码实例
2020/04/04 Python
Python pip使用超时问题解决方案
2020/08/03 Python
如何使用css3实现一个类在线直播的队列动画的示例代码
2020/06/17 HTML / CSS
广州一家公司的.NET面试题
2016/06/11 面试题
体育专业个人的求职信范文
2013/09/21 职场文书
自荐信要包含哪些内容
2013/11/06 职场文书
计算机专业优秀大学生自我总结
2014/01/21 职场文书
周年庆促销方案
2014/03/15 职场文书
小学生国庆65周年演讲稿范文(2篇)
2014/09/21 职场文书
钓鱼岛事件感想
2015/08/11 职场文书
tensorboard 可视化之localhost:6006不显示的解决方案
2021/05/22 Python
python 常用的异步框架汇总整理
2021/06/18 Python
聊聊redis-dump工具安装问题
2022/01/18 Redis
Python中三种花式打印的示例详解
2022/03/19 Python