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);
这个 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);
async function fn(){
return new Promise((fulfill,reject)=>{
// fulfill('获取用户数据');
reject('未获取到用户数据');
});
}
const result = fn();
console.log(result);
我们加上 then 方法来接受结果;
async function fn(){
return new Promise((fulfill,reject)=>{
// fulfill('获取用户数据');
reject('未获取到用户数据');
});
}
const result = fn();
result.then((value)=>{
console.log(value);
},(reason)=>{
console.warn(reason);
});
由于 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();
实践:发起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();
这是关于天气的显示结果;