ES7 之 Async/await 的使用
在 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"}
})
注意,promise 返回的仍然是 promise
下面两种方式的等效的:
1. 直接使用 promise
function ajaxPromiseGet(url) {
return new Promise(function (resolve, reject) {
$.ajax({
url: url,
type: 'GET',
success: function (res) {
resolve(res)
},
error: function (err) {
reject('请求失败')
}
})
})
}
ajaxPromiseGet(`/products/list/`).then(list => {
if (list) {
console.log(list)
}
})
2. 当需要先统一处理 promise 返回值时
function ajaxPromiseGet(url) {
return new Promise(function (resolve, reject) {
$.ajax({
url: url,
type: 'GET',
success: function (res) {
resolve(res)
},
error: function (err) {
reject('请求失败')
}
})
})
}
// 先统一处理 promise
function handleList () {
let ajaxReault = ajaxPromiseGet(`/products/list/`)
return ajaxReault.then(list => {
return list.filter(item => item.status == 0)
})
}
handleList().then(list => {
if (list) {
console.log(list)
}
})
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(); // 需要执行异步函数
源码
更多
请参考:
- https://www.cnblogs.com/cckui/p/7809813.html
- https://www.cnblogs.com/aspwebchh/p/6629333.html
- https://cnodejs.org/topic/5640b80d3a6aa72c5e0030b6
- http://es6.ruanyifeng.com/#docs/async
- https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/await
- https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Promise
ES7 之 Async/await 的使用的更多相关文章
- ES7的Async/Await的简单理解
Async/Await 的个人见解 正文: async,顾名思义,一个异步执行的功能,而 await 则是配合 async 使用的另一个关键字,也是闻字识其意,就是叫你等待啦! 二者配合食用效果更佳哦 ...
- 体验异步的终极解决方案-ES7的Async/Await
阅读本文前,期待您对promise和ES6(ECMA2015)有所了解,会更容易理解.本文以体验为主,不会深入说明,结尾有详细的文章引用. 第一个例子 Async/Await应该是目前最简单的异步方案 ...
- ES7之async/await
async 是 ES7 才有的与异步操作有关的关键字. async 函数返回一个 Promise 对象,可以使用 then 方法添加回调函数. async function helloAsync(){ ...
- ES7的async/await
async 表示这是一个async函数,await只能用在这个函数里面. await 表示在这里等待promise返回结果了,再继续执行. await 后面跟着的应该是一个promise对象 awai ...
- 让webpack打包支持ES7的async/await语法
npm install --save-dev babel-plugin-transform-runtime npm install --save babel-runtime .babelrc配置 { ...
- Promise及Async/Await
一.为什么有Async/Await? 我们都知道已经有了Promise的解决方案了,为什么还要ES7提出新的Async/Await标准呢? 答案其实也显而易见:Promise虽然跳出了异步嵌套的怪 ...
- NodeJs通过async/await处理异步
##场景 远古时代 我们在编写express后台,经常要有许多异步IO的处理.在远古时代,我们都是用chunk函数处理,也就是我们最熟悉的那种默认第一个参数是error的函数.我们来模拟一个Mongo ...
- 异步Promise及Async/Await最完整入门攻略
一.为什么有Async/Await? 我们都知道已经有了Promise的解决方案了,为什么还要ES7提出新的Async/Await标准呢? 答案其实也显而易见:Promise虽然跳出了异步嵌套的怪圈, ...
- promise 进阶 —— async / await 结合 bluebird
一.背景 1.Node.js 异步控制 在之前写的 callback vs async.js vs promise vs async / await 里,我介绍了 ES6 的 promise 和 ES ...
随机推荐
- Android View体系(五)从源码解析View的事件分发机制
1.处理点击事件的方法 View的层级 我们知道View的结构是树形的结构,View可以放在ViewGroup中,这个ViewGroup也可以放到另一个ViewGroup中,这样层层的嵌套就组成了Vi ...
- spring资源访问接口和资源加载接口
spring 资源访问接口 JDK提供的资源访问类,如java.net.URL.File等,不能很好地满足各种资源的访问需求,比如缺少从类路径或者Web容器的上下文中获取资源的操作类. 鉴于此,spr ...
- C# 异步编程4 async与await 异步程序开发
随着C#异步程序开发系列的深入,你会发现编写异步程序越发简单.事物的发展就是这样的规律,从简单到复杂再到简单. 在C# 5.0中我们可以通过async与await关键字实现快捷的异步程序开发,如下: ...
- git版本控制工具基本用法讲解(转)
一.安装Git 在linux系统使用非常方便,只需要打开shell界面,并输入: ? 1 sudo apt-get install git-core 按下回车后输入密码,即可完成Git的安装.但我们可 ...
- 微信小程序のCss(一)
一.margin:外边距:设置对象四边的外延边距. margin: 20rpx 10rpx 25rpx 10rpx :如果提供全部四个参数值,将按上.右.下.左的顺序作用于四边. margin:20r ...
- CentOS 7下安装Python3.6.4
CentOS 7下安装Python3.5 •安装python3.6可能使用的依赖 yum install openssl-devel bzip2-devel expat-devel gdbm-deve ...
- chm文件转换成html文件,解决chm文件无法使用浏览器打开的问题
每天学习一点点 编程PDF电子书免费下载: http://www.shitanlife.com/code CHM是英语“Compiled Help Manual”的简写,即“已编译的帮助文件”.CHM ...
- Codeforces Round #553 (Div. 2) D. Stas and the Queue at the Buffet 贪心+公式转化
题意 给出n个pair (a,b) 把它放在线性序列上 1--n 上 使得 sum(a*(j-1)+b*(n-j)) 最小 思路 :对式子进行合并 同类项 有: j*(a-b)+ (-a+ ...
- Zabbix 3.4.2 install && Configuration
原理: 1)zabbix server:负责接收agent发送的报告信息的核心组件,所有配置.统计数据及操作数据都由它组织进行: 2)database storage:专用于存储所有配置信息,以及由z ...
- Mybatis学习总结(三)——SqlMapConfig.xml全局配置文件解析
经过上两篇博文的总结,对mybatis中的dao开发方法和流程基本掌握了,这一节主要来总结一下mybatis中的全局配置文件SqlMapConfig.xml在开发中的一些常用配置,首先看一下该全局配置 ...