Promise & async

JavaScript 很多都是异步 (操作数据库、调用接口、操作文件)的

优点 速度快、无阻赛

缺点 需要使用大量的回调函数、编写程序起来比较复杂

异步操作经历三个阶段:

  1. 使用回调函数(原生开发时、jQuery)—-> 当写复杂程序时就会出现 嵌套多层回调函数(回调地域)
  2. ES6中出了 Promise 为了解决回调地域
  3. 基于 Promise 又出现了 async …. await ,有了这个东西之后,我们就可以写出基本上是同步的代码

功能演示:现在我们要依次调用三个接口:

  1. 登录接口(http://login.a),调用之后,返回一个令牌
  2. 有了令牌,我们在使用令牌调用第二个接口上传图片(http://upload.a),服务器返回图片的ID
  3. 有了图片ID之后我们需要再调用第三个接口(http://ys.a),对这个图片进行压缩处理

PHP实现(PHP所有操作都是同步的)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// 第一个接口
function login(){
$token = file_get_contents('http://login.a');
return $token;
}

// 第二个接口
function upload($token){
$id = file_get_contents('http://upload.a?token='.$token);
return $id;
}

// 第三个接口
function ys($id){
$newid = file_get_contents('http://ys.a?id='.$id);
return $newid;
}

// 调用接口
$token = login();
$id = upload($token);
$newid = ys($id);

JS —> 调用接口是异步的 (阶段一)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// 基于jQuery

// 阶段一、回调函数的阶段(异步:没有返回值、必须使用回调函数)
// 第一个接口
$.ajax({
url:"http://login.a",
success: function(token){
// 第二个接口
$.ajax({
url:"http://upload.a?token="+$token,
success: function(id){
// 第三个接口
$.ajax({
url:"http://ys.a?id="+$id,
success: function(newid){
console.log(newid)
}
})
}
})
}
})

缺点:

  1. 不好实现函数的封装
  2. 嵌套的回调函数太多(回调地域)

使用Promise阶段 (阶段二)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
// 第一个接口
function login(){
return new Promise(function(ok,error){
$.ajax({
url:"http://login.a",
success: function(token){
// 返回结果
ok(token)
}
})
})
}

// 第二个接口
function upload(token){
return new Promise(function(ok,error){
$.ajax({
url:"http://upload.a?token="+$token,
success: function(token){
// 返回结果
ok(token)
}
})
})
}

// 第三个接口
function ys(id){
return new Promise(function(ok,error){
$.ajax({
url:"http://ys.a?id="+$id,
success: function(token){
// 返回结果
ok(token)
}
})
})
}

// 调用接口
login().then((ret)=>{
return upload(ret)
}).then((res)=>{
return ys(res)
})

// 阶段三 async .... await

基于 Promise async …. await (阶段三 )

1
2
3
4
5
6
7
8
9
// 基于上面代码段

async function xxx(){
let token = await login()
let id = await upload(token)
let newid = await ys(id)
}
xxx()
// 注意: 所有 await 的操作必须封闭到 async 函数中

总结

  1. 把函数封装到函数中,返回一个 Promise 对象
  2. 在调用这个函数执行接口时使用 await
  3. 所有 await 操作必须写在 async 函数中