在学习ES6语法的过程中,一大难点异步处理promise的学习。所以今天就来详解的总结一下ES6中的异步处理。
同步异步
对于同步异步的概念先用白话简单的介绍一下。
同步:操作的执行有先后顺序,需要按顺序一个一个的执行。
异步:多个操作可以同时执行,且互不干扰。一般多用于数据交互。
相对比同步处理,异步处理性能好,效率高,用户体验也较好,但是之前异步操作都是通过回调函数来实现的,写起来比较复杂,可读性也较差。ES6中promise的出现,就是为了可以让我们更好,更清晰的写异步处理的代码。
promise
promise是ES6中的一个对象,用来对异步操作做一个统一的封装。下面通过一段代码来看一下promise是如何使用的。
let promise = new Promise((resolve, reject) => {
// 异步操作代码
$.ajax({
url: 'data.json',
dataType: 'json',
success(data) {
resolve(data);
},
error(err) {
reject(err);
}
})
});
p.then(data => {
alert('success');
}, res => {
alert('failed');
});
复制代码
首选需要先new一个Promise对象的实例,它的构造函数支持传入一个函数作为参数,这个函数中就是你要写的异步处理的代码。
这个函数有两个参数,分别是resolve和reject。resolve是在异步操作成功时调用,并将异步操作的结果,作为参数传递出去。reject在异步操作失败时调用,并将异步操作报出的错误,作为参数传递出去。
promise.then()是在异步操作处理完成后调用,它支持传入两个函数作为参数,第一个函数是在操作成功后执行,第二个函数是在操作失败后执行。其实这个两个函数就是上面promise中的resolve和reject,它不是promise自带的,而是你自己编写的。
在页面渲染的时候,我们需要多条数据,每次请求一个数据都要写一个promise未免有些太麻烦,有什么简单的办法呢?Promise.all()来帮你实现。
Promise.all()
Promise对象另外一个强大之处就是Promise.all方法,它用于将多个Promise实例,包装成一个新的Promise实例。
Promise.all([
//jquery封装的ajax返回的是一个promise
$.ajax({url: 'data1.json', dataType: 'json'});
$.ajax({url: 'data2.json', dataType: 'json'});
$.ajax({url: 'data3.json', dataType: 'json'});
]).then((data) => {
alert('success');
console.log(data); // [data1, data2, data3]
}, (err) => {
alert('failed');
})
复制代码
Promise.all()传入的是一个promise对象的数组,只有当其中所有的promise对象都执行完成后,才会执行then()函数。都成功后执行resolve函数,它的参数是一个数组,包含每个promise对象成功后返回的结果。要是有一个promise对象执行失败,就会执行reject函数。
虽然Promise.all()可以将我们需要的多个数据封装成一个promise对象来请求,但是还存在一个问题,如果这多个promise对象中有逻辑关系该怎么办?比如我们拿到第一个promise的对象返回的结果--用户的信息,来判断是否需要获取会员数据(第二个promise中的代码)。
很显然,这时候Promise.all()无法满足我们的需要,所以async和await出现了。
async和await
async和await的强大之处就是你完全可以用同步处理代码的写法来写异步处理的代码。既有异步处理的高性能和好的用户体验,又可以使代码简洁易读。下面通过一段代码,来感受一下它的强大。
async function getData() {
let data1 = await $.ajax({url: 'data1.json', dataType: 'json'});
if(data1) {
let data2 = await $.ajax({url: 'data2.json', dataType: 'json'});
} else {
let data3 = await $.ajax({url: 'data3.json', dataType: 'json'});
}
}
复制代码
async 放在函数声明之前,在这个函数中如果有异步处理,就使用await。await 之后必须是一个promise,它会在这个异步处理执行完成后,再执行下面的操作。这时候,如果你想要处理一些逻辑关系就非常简单了。
注: async 和 await只是把异步的操作用同步的写法写,但是背后的逻辑还是异步的,它只是一个语法糖。在执行时,它还是会被编译成类下面代码的形式。
let promise = new Promise(() => {
$.ajax({url: 'data1.json', dataType: 'json'})
}).then(data1 => {
if(data1) {
let promise = new Promise(() => {
$.ajax({url: 'data2.json', dataType: 'json'}).then(......);
}
}
});
复制代码