几乎可以在任何地方使用 async/await 吗?
Is it OK to use async/await almost everywhere?
我目前正在编写供个人使用的小型 NodeJS CLI 工具,我决定尝试使用 Babel 的 ES7 异步/等待功能。
这是一个网络工具,所以我显然有异步网络请求。我为request
包编写了一个简单的包装器:
export default function(options) {
return new Promise(function(resolve, reject) {
request({...options,
followAllRedirects: true,
headers: {
"user-agent": "Mozilla/5.0 (Windows NT 10.0; WOW64; rv:47.0) Gecko/20100101 Firefox/47.0"
}
}, (error, response, body) => {
if(error) {
return reject(error);
}
resolve({response: response, body: body});
});
});
}
现在我可以做类似的事情
async function getGooglePage() {
try {
var r = await request({url: "http://google.com"});
console.log(r.body);
console.log("This will be printed in the end.")
} catch(e) {
console.log(e);
}
}
getGooglePage();
现在我有一个问题:我在很多地方做请求,我必须将所有这些功能标记为async
,这是一种好的做法吗?我的意思是,我的代码中的几乎每个函数都应该async
,因为我需要await
其他async
函数的结果。这就是为什么我认为我误解了异步/等待的概念。
async/await 有时被称为"传染性"或"病毒式"(或者在 C# 世界中也是如此(,因为为了使其有效,它需要在整个调用链中得到支持。强制异步操作同步可能会导致意外结果,因此应将其从原始方法一直扩展到使用它的顶级使用者。换句话说,如果您创建或使用使用它的类型,则该类型也应该实现它,依此类推,一直沿链向上。所以是的,你应该为本身依赖于它的每个函数添加异步。但是请注意,您不应该将异步添加到实际上没有实现或不需要它的函数中。
试想一下:如果您使用async
(我的意思是await
某些东西(,那么您async
.避免将async
调用压缩为同步调用。
是的,我在很多地方做请求,我必须将所有这些功能标记为异步
如果你的所有代码都是异步的,那么你会在任何地方使用async
函数。
但是,将所有代码都异步会使事情变得复杂。您必须担心任何地方的竞争条件,确保正确处理可重入函数,并记住,在每await
基本上任何事情都可能发生。
我的意思是,我的代码中的几乎每个函数都应该是异步的,因为我需要等待其他异步函数的结果。
这可能不是最佳做法。您可以尝试将代码分解为较小的单元,其中大多数单元通常不是异步的。所以不是写
async function getXandThenDoY(xargs) {
let res = await get(xargs);
…
return …;
}
你应该考虑做两个函数
function doY(res) {
// synchronous
…
return …;
}
function getXandDoY(xargs) {
// asynchronous
return get(xargs).then(doY);
}
/* or, if you prefer:
async function getXandDoY(xargs) {
return doY(await get(xargs));
}
*/
我有同样的问题。
并在这里找到了一个很好的答案→"陷阱3:你的整个堆栈需要异步">
不,async/await
不会传染。 (我也相信了一段时间(
您始终可以将同步函数的结果视为承诺,然后恢复正常。
从 developer.mozilla.org:
异步函数声明定义了一个异步函数...
返回值: 一个承诺,它将用价值解决 由异步函数返回,或因未捕获的异常而被拒绝 从异步函数中抛出。
示例代码:
const log = console.log; // just lazy shorthand
// just to delay, as seen in many places
function promiseTimeout(time, value) {
return new Promise(function(resolve, reject) {
setTimeout(function() { resolve(value); }, time);
});
};
// the thing you care about
async function foo() {
Promise.resolve('here')
.then((a) => {log('doing stuff '+a); return 'pear'})
.then(function(v) {
return promiseTimeout(1000,v)
});
};
// treat async-function like promise:
foo().then(function(){ log('folling up in main, ')});
// log('bad end');
得到你:
doing stuff here
following up in main
启用"坏结局"会过早出现。你只能等待你使用的东西等待。(如果你这样做了,请记住:这只是语法糖,省去了你把后续代码塞进.then()
的分类......不错,但仅此而已。
- 如何在 es6 javascript 类中使用 async/await
- 使用Babel.js的Transpile Async Await提案
- 为什么babel将async/await转换为再生器
- 如何在我的gulpfile.babel.js中使用ES2016/ES7提案进行async/await
- Nodejs中的async/await替换
- async/await w/ koa 2 & mongoose
- 如何在 Node JS FS 模块中使用 Typescript Async/ await with promise
- Typescript async/await and angular $q service
- 几乎可以在任何地方使用 async/await 吗?
- 将 redux-saga 与 ES6 生成器与 ES2017 async/await 一起使用 redux-thunk
- 如何在Gulp 4中使用async/await
- Typescript async/await Promise调用差异
- async/await and recursion
- javascript : Async/await in .replace
- babel 6 async/await:意外的令牌
- 如何在流中使用ES8 async/await
- 如何使用async/await捕获抛出的错误
- JavaScript async/await and do/while loop
- 节点回调以 async/await 承诺
- 我如何在Koa.js应用程序的验收测试中使用ES2016 (ES7) async/await ?