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 相关文章推荐
javascript XML数据显示为HTML一例
Dec 23 Javascript
javascript 构造函数强制调用经验总结
Dec 02 Javascript
JavaScript程序员应该知道的45个实用技巧
Mar 04 Javascript
jquery delay()介绍及使用指南
Sep 02 Javascript
node.js中的fs.writeSync方法使用说明
Dec 15 Javascript
jQuery中andSelf()方法用法实例
Jan 08 Javascript
jQuery代码实现实时获取时间
Jan 29 Javascript
简单实现jQuery弹幕效果
May 06 jQuery
详解JavaScript原生封装ajax请求和Jquery中的ajax请求
Feb 14 jQuery
vue组件间的参数传递实例详解
Apr 26 Javascript
关于引入vue.js 文件的知识点总结
Jan 28 Javascript
vue-treeselect的基本用法以及解决点击无法出现拉下菜单
Apr 30 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
生成sessionid和随机密码的例子
2006/10/09 PHP
利用PHP实现短域名互转
2013/07/05 PHP
laravel执行php artisan migrate报错的解决方法
2019/10/09 PHP
PHP Swoole异步MySQL客户端实现方法示例
2019/10/24 PHP
Blocksit插件实现瀑布流数据无限( 异步)加载
2014/06/20 Javascript
JavaScript中的object转换成number或string规则介绍
2014/12/31 Javascript
JavaScript实现的伸展收缩型菜单代码
2015/10/14 Javascript
原生js实现手风琴功能(支持横纵向调用)
2017/01/13 Javascript
JS实现微信摇一摇原理解析
2017/07/22 Javascript
Angular实现较为复杂的表格过滤,删除功能示例
2017/12/23 Javascript
Node.js模拟发起http请求从异步转同步的5种用法
2018/09/26 Javascript
vue 本地服务不能被外部IP访问的完美解决方法
2018/10/29 Javascript
微信小程序实现获取准确的腾讯定位地址功能示例
2019/03/27 Javascript
vue router 跳转时打开新页面的示例方法
2019/07/28 Javascript
javascript实现拖拽碰撞检测
2020/03/12 Javascript
jQuery实现简单日历效果
2020/07/05 jQuery
Nuxt的路由动画效果案例
2020/11/06 Javascript
vue封装自定义指令之动态显示title操作(溢出显示,不溢出不显示)
2020/11/12 Javascript
python使用append合并两个数组的方法
2015/04/28 Python
使用Python对Excel进行读写操作
2017/03/30 Python
利用python提取wav文件的mfcc方法
2019/01/09 Python
Python设计模式之适配器模式原理与用法详解
2019/01/15 Python
使用django实现一个代码发布系统
2019/07/18 Python
解决Tensorflow 内存泄露问题
2020/02/05 Python
windows支持哪个版本的python
2020/07/03 Python
Python map及filter函数使用方法解析
2020/08/06 Python
英国最受欢迎的母婴精品品牌:JoJo Maman BéBé
2021/02/17 全球购物
全球最大的瓷器、水晶和银器零售商:Replacements
2020/06/15 全球购物
请问如下代码执行后a和b的值分别是什么
2016/05/05 面试题
班级活动策划书
2014/02/06 职场文书
给校长的建议书
2014/03/12 职场文书
财务工作失误检讨书
2015/02/19 职场文书
法律进社区活动总结
2015/05/07 职场文书
给原生html中添加水印遮罩层的实现示例
2021/04/02 Javascript
Go语言基础map用法及示例详解
2021/11/17 Golang
MySQL事务操作的四大特性以及并发事务问题
2022/04/12 MySQL