async 和 await 两种语法结合可以让异步代码像同步代码一样;

可以先回顾一下 ​​promise ​​; 


async函数

声明一个 async 函数,只要在普通的函数前面加一个 async 就可以了;

1) async 函数的返回值为 promise 对象;

2) promise 对象的结果由 async 函数执行的返回值决定;

async function fn(){
// 返回字符串
return 'hello';
}

fn 本来是个普通的函数,在前面加上 async 后,就变成了一个 async 函数,这是个特殊的函数,特殊就在于,这个函数会返回一个 promise 对象。即使返回的是一个字符串;

可以看一下:

const result = fn();
console.log(result);

Javascript(笔记45) - ES8特性 - async 和 await_ajax

这个 promise 对象的状态是 fulfilled 成功状态,值为 hello;

1) 只要返回的不是 promise 类型的对象,则这个函数的返回结果,就是状态为成功的 promise ;

async function fn(){
return ;
}
const result = fn();
console.log(result);

即使是 return 个 undefined ;那返回的结果也是状态为成功的 promise 对象;

2)返回的结果是抛出错误的话,那返回的结果,就是状态为失败的 promise; 

async function fn(){
throw new Error('error'); // 抛出错误
}
const result = fn();
console.log(result);

3)返回的结果是一个 promise 对象的话,那这个函数返回结果的状态就是 Promise 对象返回的状态;

也就是说:

promise 对象返回的状态是 fulfill ,那函数返回的结果的状态也是成功:fulfilled ;

promise 对象返回的状态是 reject ,那函数返回的结果状态就是失败:rejected; 

async function fn(){
return new Promise((fulfill,reject)=>{
fulfill('获取用户数据');
});
}
const result = fn();
console.log(result);

Javascript(笔记45) - ES8特性 - async 和 await_ajax_02

async function fn(){
return new Promise((fulfill,reject)=>{
// fulfill('获取用户数据');
reject('未获取到用户数据');
});
}
const result = fn();
console.log(result);

Javascript(笔记45) - ES8特性 - async 和 await_async_03

我们加上 then 方法来接受结果;

async function fn(){
return new Promise((fulfill,reject)=>{
// fulfill('获取用户数据');
reject('未获取到用户数据');
});
}
const result = fn();
result.then((value)=>{
console.log(value);
},(reason)=>{
console.warn(reason);
});

Javascript(笔记45) - ES8特性 - async 和 await_javascript_04

由于 promise 返回的是 reject 失败状态,那么 then 方法将调用第二个函数来处理,返回值是:“未获取到用户数据”;


await表达式

和 async 结合使用;

1)await 必须写在 async 函数中,单向依赖;

2)await 右侧的表达式一般为 promise 对象;

3)awat 返回的是 promise 成功的值;

4)await 的 promise 失败了,就会抛出异常,需要通过 try ... catch 捕获处理;

// 创建promise对象
const p = new Promise((fulfill, reject) => {
fulfill('成功获取用户数据');
});
// await 放在 async 函数中
async function main() {
let result = await p;
console.log(result);
}

main(); // 成功获取用户数据

这个 p 对象,是有两个属性的,一个是 promise 的状态,一个是返回值;async 函数通过 await 的引用,直接把 promise 返回的“成功状态的值”拿来用了;那要是失败状态呢? 

// 创建promise对象
const p = new Promise((fulfill, reject) => {
// fulfill('成功获取用户数据');
reject('未获取到用户数据');
});
// await 放在 async 函数中
async function main() {
try {
let result = await p;
console.log(result);
} catch (e) {
console.log(e);
}
}

main(); // 未获取到用户数据

失败状态的话,通过 try ... catch 把 promise 返回的“失败状态的值”捕获到;


实践:读取文件

读取三个文件的内容;

借助 node.js 的读取文件模板,所以需要安装 node.js ;

新建一个  readfile.js 文件,代码就写在这个文件中;

// 引入 fs 模板
const fs = require('fs');

// 分别读取笔记123
function readBj1() {
return new Promise((fulfill, reject) => {
fs.readFile('./res/笔记1.md', 'utf8', (err, data) => {
// 如果失败
if (err) reject(err);
// 如果成功
fulfill(data);
});
});
}

function readBj2() {
return new Promise((fulfill, reject) => {
fs.readFile('./res/笔记2.md', 'utf8', (err, data) => {
// 如果失败
if (err) reject(err);
// 如果成功
fulfill(data);
});
});
}

function readBj3() {
return new Promise((fulfill, reject) => {
fs.readFile('./res/笔记3.md', 'utf8', (err, data) => {
// 如果失败
if (err) reject(err);
// 如果成功
fulfill(data);
});
});
}

async function main() {
// 分别获取笔记123的内容
let bj1 = await readBj1();
let bj2 = await readBj2();
let bj3 = await readBj3();

console.log(bj1.toString());
console.log(bj2);
console.log(bj3);
}
main();

Javascript(笔记45) - ES8特性 - async 和 await_ES8_05


实践:发起AJAX请求

发送AJAX请求,返回的结果是 promise 对象;

先写一个 promise then 方法的测试,这是以前的做法;

function sendAJAX(url){
return new Promise((fulfill,reject)=>{
const x = new XMLHttpRequest();
x.open('get',url);
x.send();
x.onreadystatechange = function(){
if(x.readyState === 4){
if(x.status >= 200 && x.status <300){
fulfill(x.response);
}else{
reject(x.status);
}
}
}
});
}
let url = 'https://api.apiopen.top/api/sentences';

sendAJAX(url).then((value)=>{ // 接个 then 方法
console.log(value);
},(reason)=>{
console.log(reason);
});

再写一个 async 和 await 结合的:借用上面封装好的 sendAJAX() 函数;

let apiUrlOne = 'https://api.apiopen.top/api/sentences';
let apiUrlTwo = 'https://v0.yiketianqi.com/api?unescape=1&version=v91&appid=43656176&appsecret=I42og6Lm&ext=&cityid=&city=';

async function main(){
let resInfo = await sendAJAX(apiUrlOne);
console.log(resInfo);
let resTQ = await sendAJAX(apiUrlTwo);
console.log(resTQ);
}
main();

Javascript(笔记45) - ES8特性 - async 和 await_ajax_06

这是关于天气的显示结果;