async函数
- Generator 函数的语法糖 使异步操作更简单
async
表示函数里有异步操作,await
表示紧跟在后面的表达式需要等待结果。返回值 一个Promise对象,可以用then方法指定下一步操作
- async函数return的值通过Promise对象resolved时候的data获取
- async函数throw的错误通过Promise对象rejected时候的error获取
async function test() {
return 1;
}
const p = test();
console.log(p); // Promise {<resolved>: 1}__proto__: Promise[[PromiseStatus]]: "resolved"[[PromiseValue]]: 1
p.then(function(data) {
console.log(data); // 1
});
async function test() {
throw new Error("error");
}
const p = test();
console.log(p); // Promise {<rejected>: Error: error...}
p.catch(function(err) {
console.log(err); // Error: error
});
await
- await命令只能用在async函数之中
- await后可以是Promise对象和原始类型的值(数值、字符串和布尔值,但这时会自动转成立即resolved的Promise对象)
- await后Promise对象状态变为rejected,后续执行中断
await后Promise对象状态为resolved
async function async1() {
console.log("async1 start");
let r = await async2();
console.log(r)
console.log("async1 end");
}
async function async2() {
return Promise.resolve().then(_ => {
console.log("async2 promise");
return "value from async2"
});
}
async1();
- 执行async1,打印"async1 start"
- 执行await async2(),await会等待Promise变成resolved状态,然后拿到返回值,因此会执行Promise.resolve().then(),打印"async2 promise"
- async2中then函数返回的值被赋值给r,打印"value from async2"
- 打印"async1 end"
await后Promise对象状态为reject
await Promise.reject("error")后的代码不会被执行
async function f() {
await Promise.reject("error");
console.log(1);
await 100;
}
f();
处理异常后,后面的代码就会执行了
通过Promise 对象的
catch
方法async function f() { await Promise.reject("error").catch(err => { // 处理异常 }); console.log(1); await 100; } f();
通过try{}catch{}捕获异常
async function f() { try { await Promise.reject("error"); } catch { // 处理异常 } console.log(1); await 100; } f();
实现原理
Generator + 自动执行器
// 使用async函数 返回Promise对象
async function example(params) {
// ...
}
// 实现
function example(params) {
return spawn(function*() {
// ...
});
}
function spawn(genF) {
return new Promise(function(resolve, reject) {
const gen = genF(); // 生成器对象
function step(nextF) {
let next;
try {
next = nextF(); // 执行gen.next
} catch (e) {
return reject(e);
}
if (next.done) {
return resolve(next.value);
}
Promise.resolve(next.value).then(
function(v) {
step(function() {
return gen.next(v);
});
},
function(e) {
step(function() {
return gen.throw(e);
});
}
);
}
step(function() {
return gen.next(undefined);
});
});
}
应用
按顺序打印文件
Promise实现
function readFilesByPromise() {
const fs = require('fs')
const path = require('path')
const files = [
'./file/a.json',
'./file/b.json',
'./file/c.json'
]
function readFile(url) {
return new Promise((resolve, reject) => {
fs.readFile(path.join(__dirname, url), function (err, data) {
if (err) { reject(err) }
resolve(data)
})
})
}
readFile(files[0])
.then((data) => {
console.log(data.toString())
return readFile(files[1])
})
.then((data) => {
console.log(data.toString())
return readFile(files[2])
})
.then((data) => {
console.log(data.toString())
})
}
readFilesByPromise()
async/await实现
async function readFilesByAsync() {
const fs = require('fs')
const path = require('path')
const files = [
'./file/a.json',
'./file/b.json',
'./file/c.json'
]
function readFile(url) {
return new Promise((resolve, reject) => {
fs.readFile(path.join(__dirname, url), function (err, data) {
if (err) { reject(err) }
resolve(data)
})
})
}
const str1 = await readFile(files[0])
console.log(str1.toString())
const str2 = await readFile(files[1])
console.log(str2.toString())
const str3 = await readFile(files[2])
console.log(str3.toString())
}
readFilesByAsync()
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。