在 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(); // 需要执行异步函数

源码

源码查看

更多

请参考:

ES7 之 Async/await 的使用的更多相关文章

  1. ES7的Async/Await的简单理解

    Async/Await 的个人见解 正文: async,顾名思义,一个异步执行的功能,而 await 则是配合 async 使用的另一个关键字,也是闻字识其意,就是叫你等待啦! 二者配合食用效果更佳哦 ...

  2. 体验异步的终极解决方案-ES7的Async/Await

    阅读本文前,期待您对promise和ES6(ECMA2015)有所了解,会更容易理解.本文以体验为主,不会深入说明,结尾有详细的文章引用. 第一个例子 Async/Await应该是目前最简单的异步方案 ...

  3. ES7之async/await

    async 是 ES7 才有的与异步操作有关的关键字. async 函数返回一个 Promise 对象,可以使用 then 方法添加回调函数. async function helloAsync(){ ...

  4. ES7的async/await

    async 表示这是一个async函数,await只能用在这个函数里面. await 表示在这里等待promise返回结果了,再继续执行. await 后面跟着的应该是一个promise对象 awai ...

  5. 让webpack打包支持ES7的async/await语法

    npm install --save-dev babel-plugin-transform-runtime npm install --save babel-runtime .babelrc配置 { ...

  6. Promise及Async/Await

      一.为什么有Async/Await? 我们都知道已经有了Promise的解决方案了,为什么还要ES7提出新的Async/Await标准呢? 答案其实也显而易见:Promise虽然跳出了异步嵌套的怪 ...

  7. NodeJs通过async/await处理异步

    ##场景 远古时代 我们在编写express后台,经常要有许多异步IO的处理.在远古时代,我们都是用chunk函数处理,也就是我们最熟悉的那种默认第一个参数是error的函数.我们来模拟一个Mongo ...

  8. 异步Promise及Async/Await最完整入门攻略

    一.为什么有Async/Await? 我们都知道已经有了Promise的解决方案了,为什么还要ES7提出新的Async/Await标准呢? 答案其实也显而易见:Promise虽然跳出了异步嵌套的怪圈, ...

  9. promise 进阶 —— async / await 结合 bluebird

    一.背景 1.Node.js 异步控制 在之前写的 callback vs async.js vs promise vs async / await 里,我介绍了 ES6 的 promise 和 ES ...

随机推荐

  1. XSS(跨站脚本攻击)漏洞解决方案

    首先,简单介绍一下XSS定义: 一 . XSS介绍 XSS是跨站脚本攻击(Cross Site Scripting)的缩写.为了和层叠样式表CSS(Cascading Style Sheets)加以区 ...

  2. scala spark 机器学习初探

    Transformer: 是一个抽象类包含特征转换器, 和最终的学习模型, 需要实现transformer方法 通常transformer为一个RDD增加若干列, 最终转化成另一个RDD, 1. 特征 ...

  3. python第九十五天--js正则

    定义正则表达式 /.../ 用于定义正则表达式 /.../g 表示全局匹配 /.../i 表示不区分大小写 /.../m 表示多行匹配 JS正则匹配时本身就是支持多行,此处多行匹配只是影响正则表达式^ ...

  4. 【PAT】1083 是否存在相等的差(20 分)

    //这题不是我耍流氓,实在太简单,只能直接贴代码了,凑个数 #include<stdio.h> int aaa[10005]={0}; int main(){ int N;scanf(&q ...

  5. 菜鸟水平如何在Android Studio中添加uiautomator测试框架

    1.启动AS,弹出创建Android Studio项目 2.选择 "Start a new Android Studio project",输入 application name ...

  6. node学习笔记_04 express相册

    学习node用express框架做了一个相册展示及上传功能: 1.没有连接服务器,这里全部是操作文件夹 2.安装上传文件的依赖formidable,npm install --save formida ...

  7. C#常见委托のdelegate定义,Func,Action,Predicate总结

    委托,顾名思义,就是让其他代理,本质就是为具有共性方法组定义一个方法模板:(交流可以加qq群:435226676) 委托常见的方式有一般委托显示定义,Func<T,TResult> (T, ...

  8. UVa 11846 - Finding Seats Again

    链接: https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem& ...

  9. DStream算子讲解(一)

    先把目录列好,方便有条理的进行整理

  10. 如何使用bootstrap框架

    Bootstrap是前端工程师比较常用的框架.插件,根据它的定义,Bootstrap就是用于前端开发的一个模板,就是别人做好了我们直接可以搬过来直接使用或者根据自己需要略加修改设计自己的页面效果的成品 ...