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 ...
随机推荐
- Kotlin入门(10)七十二变的输入参数
上一篇文章介绍了Kotlin对函数的基本用法,包括函数的定义.输入参数的声明.输出参数的声明等等,这些足够对付简单的场合了.当然了,倘若一门新语言仅仅满足于这些雕虫小技,那也实在没什么前途.既然Kot ...
- system.img镜像转换为system.new.dat + system.transfer.list
android 8.1上面验证,支持所有的android版本,直接放到sdk中执行即可. img2sdat.py #!/usr/bin/env python #coding=utf-8 imp ...
- Scala并发编程【消息机制】
1.入门 package actor import scala.actors.Actor import scala.actors.migration.ActorDSL /** * Created by ...
- linux kernel 源码安装
有时我们在安装系统后,发现没有安装当前系统的内核源码在/usr/src/kernels目录下,其实我们是少安装了一个rpm包: 当你配置好yum源后: yum install kernel-devel ...
- Django学习---快速搭建搜索引擎(haystack + whoosh + jieba)
Django下的搜索引擎(haystack + whoosh + jieba) 软件安装 haystack是django的开源搜索框架,该框架支持Solr,Elasticsearch,Whoosh, ...
- Opengl正交矩阵 glOrthof 数学原理(转)
http://blog.sina.com.cn/s/blog_6084f588010192ug.html 在opengles1.1中设置正交矩阵只要一个函数调用就可以了:glOrthof,但是open ...
- C语言变量定义与数据溢出(初学者)
1.变量定义的一般形式为:类型说明符.变量名标识符等:例:int a,b,c;(abc为整型变量) 在书写变量定义时应注意以下几点: (1)允许在一个类型说明符后,定义多个相同类型的变量.各变量之间用 ...
- (14)Python类
- API与软件架构-接口
http://blog.csdn.net/horkychen/article/details/46612899 从架构设计的角度来看(所谓的组成论),软件系统就是模块和接口. 模块(层次/组件)决定分 ...
- 在Debian系中快速有效的安装oracle-java
jre8下载链接 https://www.oracle.com/technetwork/java/javase/downloads/jre8-downloads-2133155.html oracl ...