JS异步编程的那些事(二)

      上篇文章说完了 Promise 对象、fetch 方法。这篇我们接着说说 ES7 中丢出的语法糖,”异步终极解决方法 Async/await“。以及分别用 fetch 和 Async/await 去封装一个增删改查的库。

Async/await

      async 和 await 是 js 中异步最终极的解决方案。可以很舒适地与 promise 协同工作。但兼容一般,我们可以用 polyfill(js 修补器)兼容一下,polyfill 是一个 js 库、专门用于处理 js 的兼容性问题。但是确实很难做到 100%覆盖。我们先来看看 async 的用法。

Async/await 用法

显而易见这是一个普通到不行的函数

1
2
3
4
function myFunc() {
return "Hello world";
}
console.log(myFunc()); //Hello world

我们来看看加了 async 之后呢?

1
2
3
4
async function myAsync() {
return "Hello world"
}
console.log(myAsync()); //Promise {<resolved>: "Hello world"}

      看到了吗?在函数前面加了 async(异步) 关键字,就表示该函数是异步函数。这个函数就会返回一个 Promise,且代码中有 return 语句非 Promise 语句时,JS 就会自动的把 return 中的”Hello world“包装成 Promise 的 resolved 值。语法是不是敲极的简单呢?接下来我们看看 await 是如何搭配 Async 一起使用的呢。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
async function asyncWait() {
const pro = new Promise((resolve, reject) => {
setTimeout(() => { resolve("hello world") }, 2000);
});
const error = false;
if (error) {
await Promise.reject(new Error("报错了"));
} else {
//等待pro执行完毕后才会执行
const res = await pro;
return res;
}
}
asyncWait().then((data) => {
console.log(data); //Hello world
}).catch((err) => {
console.log(err);
});

      我们在 async 声明的函数体内,使用了 await 关键字。当函数执行的时候,一旦遇到 await 就会先返回,等到异步操作完成之后,再去执行函数体内后面的语句。这里要注意的是:不能在常规函数里使用 await,否则会出现语法错误。await 和 async 就好比一对连体婴。await 只能在 async 函数中工作。我们来看看如果不使用 await 会有什么效果。

1
2
3
4
5
6
async function please() {
const response = fetch("http://jsonplaceholder.typicode.com/posts");
const data = response.json(); //response.json is not a function
return data;
}
please().then(data => console.log(data));

      以上代码控制台中报错:response.json is not a function。我们看到没有在 await,下面的 response.json()就会报错,因为 response 还没有执行完。如果加了 await,就会在当前请求成功后再往下走。await 表示等一下,只有当 await 定义的行数执行完毕后代码才会继续往下执行。大多情况下 await 后面的应该跟一个 Promise 的对象或者 fetch。我们看看加了 await 关键词后的执行效果。

1
2
3
4
5
6
async function please() {
const response = await fetch("http://jsonplaceholder.typicode.com/posts");
const data = await response.json();
return data;
}
please().then(data => console.log(data)); (100) [{…}, {…},...]

封装增删改查方法

fetch 库

      完整的代码已经上传到我的github 仓库。以下将记录 fetch 封装增删改查的关键代码。

查看数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class EasyHttp {
get(url) {
return new Promise((resolve, reject) => {
fetch(url)
.then((res) => res.json())
.then((data) => { resolve(data) })
.catch(err => { reject(err) });
});
}
}
//调用方式
const http = new EasyHttp;
http.get("data/test.json")
.then((data) => {
console.log(data); //(6) [{…}, {…}, {…}, {…}, {…}, {…}]
})
.catch((err) => {
console.log(err);
});

增加数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
post(url, data) {
return new Promise((resolve, reject) => {
fetch(url, {
//发送请求方法,一般用大写
method: 'POST',
//http的头信息
headers: {
'content-type': 'application/json'
},
//请求体,将对象转成字符串
body: JSON.stringify(data)
})
.then(res => res.json())
.then(data => resolve(data))
.catch(err => reject(err))
});
}

修改数据

1
2
3
4
5
6
7
8
9
10
11
12
13
put(url, data) {
return new Promise((resolve, reject) => {
fetch(url, {
method: 'PUT',
headers: {
'content-type': 'application/json'
},
body: JSON.stringify(data)
}).then(res => res.json())
.then(data => resolve(data))
.catch(err => reject(err))
});
}

删除数据

1
2
3
4
5
6
7
8
9
10
11
12
delete(url) {
return new Promise((resolve, reject) => {
fetch(url, {
method: 'DELETE',
headers: {
'Content-type': 'application/json'
}
}).then(res => res.json())
.then(data => resolve("删除成功"))
.catch(err => reject(err));
});
};

      看完了 fetch 的写法,接下来我们看看如何用 async/await 如何更优雅的实现。

async/await 封装

查看数据

1
2
3
4
5
6
async get(url) {
const response = await fetch(url);
//将Promise对象转成json对象
const data = await response.json();
return data;
}

增加数据

1
2
3
4
5
6
7
8
9
10
11
async post(url, data) {
const response = await fetch(url, {
method: 'POST',
headers: {
'content-type': 'application/json'
},
body: JSON.stringify(data)
});
const postData = await response.json();
return postData;
}

修改数据

1
2
3
4
5
6
7
8
9
10
11
async put(url, data) {
const response = await fetch(url, {
method: 'PUT',
headers: {
'content-type': 'application/json'
},
body: JSON.stringify(data)
});
const putData = await response.json();
return putData;
}

删除数据

1
2
3
4
5
6
7
8
9
10
async delete(url) {
const response = await fetch(url, {
method: 'DELETE',
headers: {
'Content-type': 'application/json'
}
});
const deleteData = await "成功删除数据";
return deleteData;
};

      从代码量上,我们可以显而易见的对比出 async/await 代码量明显少很多,我们不再需要书写 Promise 了。也不需要那么多的.then.then,代码看上去更加优雅,编写出的异步代码更易于读写。只要加一个 async,一个函数就可以作为 promise 对象返回回去 ,等待 resolve 执行完毕后,再去实行。让我们书写异步代码的时候像同步的方式一样舒畅。用 async/await 编写的异步代码更简单易懂,从视觉上就能感觉到复杂度降低了。

Copyright ©2019 guowj All Rights Reserved.

访客数 : | 访问量 :