同步思维解决异步流程
前言
有时候当业务复杂时,我们需要在Ajax中再实现多次请求,这样就会让代码重复嵌套,十分不美观。
有些人就会认为,既然我不想嵌套,那就将数据返回出来再操作呗?来看看下面的例子:
function request() {
$.ajax({
url: '',
data: '',
methods: 'Get',
success: (data) => {
//data为接受到后台的数据
return data
}
})
}
let data = request()
事实是,此时的data是无法获取到Ajax中的data,因为request()返回是Ajax的回调。为了解决这个问题,ES6中有一个十分迷人的对象正向你抛出橄榄枝——promise。
Promise对象
Promise 对象代表一个异步操作,有三种状态:Pending(进行中)、Resolved(已完成,又称 Fulfilled)和 Rejected(已失败)。只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。
-
Promise 构造函数接受一个函数作为参数,该函数的两个参数分别是
resolve
方法和reject
方法。 -
如果异步操作成功,则用
resolve
方法将 Promise 对象的状态,从「未完成」变为「成功」(即从 pending 变为 resolved); -
如果异步操作失败,则用
reject
方法将 Promise 对象的状态,从「未完成」变为「失败」(即从 pending 变为 rejected)。 -
基础语法如下:
var promise = new Promise(function(resolve, reject) {
if (/* 异步操作成功 */){
resolve(value);
} else {
reject(error);
}
});
promise.then(function(value) {
// success
}, function(value) {
// failure
}
);
因此,上面的代码就可以修改为:
function request() {
return new Promise( resolve=>{
$.ajax({
url: '',
data: '',
methods: 'Get',
success: (data) => {
//利用resolve告诉promise,操作完成,并返回数据data
resolve(data)
}
})
}
let res = request().then(result=>{
console.log(result);
}
异步函数
语法:再function前加上关键字async
:
async function test() {
}
它的返回值会返回一个promise对象。可以给我们进行链式处理,例如:
async function helloAsync(){
return "helloAsync";
}
console.log(helloAsync()) // Promise {<resolved>: "helloAsync"}
helloAsync().then(v=>{
console.log(v); // helloAsync
})
还有一个作用就是可以阻塞异步操作,使用关键字await
:
await
只在异步函数里面才起作用。它可以放在任何异步的,基于 promise 的函数之前。它会暂停代码在该行上,直到 promise 完成,然后返回结果值(省略了then,直接获得数据)。在暂停的同时,其他正在等待执行的代码就有机会执行了。
function request() {
return new Promise((resolve, reject) => {
setTimeout(() => {
let data = {
code: 1,
message: '成功',
data: {}
}
resolve(data)
}, 1000)
})
}
async function test() {
let data = await request() //等待request()返回data
console.log(data) //打印出data的内容
}
test() //返回一个promise对象
注意:await操作只能够阻塞promise对象,如果没有promise对象是无法阻塞成功的,并且只能够用在async中