Node.js7.6起, Node.js 搭载了有async函数功能的V8引擎。当Node.js 8于10月31日成为LTS版本后,我们没有理由不使用async函数。接下来,我将简要介绍async函数,以及如何改变我们编写Node.js应用程序的方式。
async函数可以让你编写基于Promise的代码使他像同步的一样。每当你用asnyc关键字定义了一个函数体,你可以在函数体内使用 await关键字。当这个async函数被调用,会得到一个Promise实例。当async函数返回值时这个promise会执行。如果async函数抛出错误,那么会进入promise的rejected流程。
await关键字可以用来等待Promise 进入 resolved并有完成返回值。如果传给await的值不是Promise实例,它会被转为 Promise的 resolved 流程。
const rp = require('request-promise');
async function main () {
const result = await rp('https://google.com');
const twenty = await 20;
// sleeeeeeeeping for a second
await new Promise (resolve => {
setTimeout(resolve, 1000);
});
return result
}
main()
.then(console.log)
.catch(console.error);
如果你的Node.js应用已经使用了Promise, 你只需要使用 await替代Promise链式调用。如果你的代码是基于 callback, 迁移到 async函数需要逐步修改现有代码。可以在新到功能中使用新的技术,如果必须保留旧有功能则可以使用 Promise 进行简单的包装。为此你可以使用内置的util.promisify(译者注:Node.js 8.0+) 方法!
const util = require('util');
const {readFile} = require('fs');
const readFileAsync = util.promisify(readFile);
async function main () {
const result = await readFileAsync('.gitignore');
return result
}
main()
.then(console.log)
.catch(console.error);
As express supports Promises out of the box, using async functions with express is as simple as:
express 是支持 Promise的,所以使用async函数可以把代码简化为:
const express = require('express');
const app = express();
app.get('/', async (request, response) => {
// awaiting Promises here
// if you just await a single promise, you could simply return with it,
// no need to await for it
const result = await getContent();
response.send(result);
});
app.listen(process.env.PORT);
Edit1:如Keith Smith所指出的那样,上面的例子有一个严重的问题 - 如果Promise进入rejected,express路由处理程序就会hang住,因为那里没有错误处理。
要解决这个问题,你应该把你的异步处理程序封装在一个处理错误的函数中:
const awaitHandlerFactory = middleware => {
return async (req, res, next) => {
try {
await middleware(req, res, next)
} catch (err) {
next(err)
}
}
}
// and use it this way:
app.get('/', awaitHandlerFactory(async (request, response) => {
const result = await getContent();
response.send(result);
}));
假设你正在做类似的事情,当一个操作需要两个输入,一个来自数据库,另一个来自外部服务:
async function main () {
const user = await Users.fetch(userId);
const product = await Products.fetch(productId);
await makePurchase(user, product);
}
在这个case中,将会发生以下情况:
正如所见,你可以同时做前两个操作,因为它们之间没有依赖关系。 为此应该使用 Promise.all 方法:
async function main () {
const [user, product] = await Promise.all([
Users.fetch(userId),
Products.fetch(productId)
]);
await makePurchase(user, product);
}
在某些情况下,您只需要最快resolving得到Promise的结果 - 在这种情况时可以使用Promise.race方法。
参考下面的代码
async function main () {
await new Promise((resolve, reject) => {
reject(new Error(''));
});
};
main()
.then(console.log);
如果运行这段代码,你会在terminal上看到类似的消息:
(node:69738) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 2): Error:
(node:69738) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
在新版的Node.js中,如果Promise拒绝不会被处理,那么会导致整个Node.js进程崩溃。 因此在必要时应该使用try-catch语句:
const util = require('util');
async function main () {
try {
await new Promise((resolve, reject) => {
reject(new Error(' '));
});
}
catch (err) {
// handle error case
// maybe throwing is okay depending on your use-case
}
}
main()
.then(console.log)
.catch(console.error);
但是如果使用try-catch会丢失重要的异常如系统错误,那么就要重新抛出异常。 要了解更多关于什么时候应该重新投掷的信息,我强烈建议阅读Eran的Learning to Throw Again.。
Node.js的第一个异步控制流库是由 Caolan McMahon 编写的一async的异步控制流库。 它提供了多个异步助手:
如果你不想重新造轮子,而且不想使用这个库,那么可以重度使用 async函数和 util .promisify方法:
const util = require('util');
const async = require('async');
const numbers = [
1, 2, 3, 4, 5
];
mapLimitAsync = util.promisify(async.mapLimit);
async function main () {
return await mapLimitAsync(numbers, 2, (number, done) => {
setTimeout(function () {
done(null, number * 2);
}, 100)
});
};
main()
.then(console.log)
.catch(console.error);
虽然大家知道async/await,但是很多人对这个方法中内部怎么执行的还不是很了解,本文是我看了一遍技术博客理解 JavaScript 的 async/await
Async实际上是一个封装了自动化执行并返回一个Promise的Generator函数的语法糖。这句话的意思我们可以分为三个部分来解读:首先它有一个自动化执行,Generator函数是依靠不停的调用.net来依次执行的,Async有一个自动化执行的过程
自2015年11 发布1.7版以来,TypeScript 已支持 async/await 关键字。编译器使用 yield 将异步函数转换为生成器函数。这意味着咱们无法针对 ES3 或 ES5,因为生成器仅在 ES6 中引入的。
async/await 大家肯定都用过,在处理异步操作的时候真的是很方便。那今天主要讲一些在使用 async/await 时容易忽略和犯错的地方。上面的代码中,每一行都会 等待上一行的结果返回后才会执行。
有一个图片列表,我想要在图片onload成功之后获取加载成功的图片列表,图片资源加载为异步,我们使用ES7的async await方式实现,多张图片,是用for循环。
Async 和 Awaiit 是 Promise 的扩展,我们知道 JavaScript 是单线程的,使用 Promise 之后可以使异步操作的书写更简洁,而 Async 使 Promise 像同步操作
最近代码写着写着,我突然意识到一个问题——我们既然已经有了 Promise 和 then,为啥还需要 async 和 await?这不是脱裤子放屁吗?
如果让你手写async函数的实现,你是不是会觉得很复杂?这篇文章带你用20行搞定它的核心。经常有人说async函数是generator函数的语法糖,那么到底是怎么样一个糖呢?让我们来一层层的剥开它的糖衣。
async/await是ES7的写法,可以让非同步call back写法看起来像同步的顺序去执行。以下我们new一个Promise的class并return给一个function
决心还是起来把今天白天工作期间反问一个小伙伴的async&await问题。实际上这个问题之前我就一直想写点什么,只是奈何懒的很,一直没有行动
内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!