我目前正在编写用于个人用途的小型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
函数的结果。这就是为什么我认为我误解了异步/等待概念。
答案 0 :(得分:9)
async / await有时被称为"传染性"或"病毒" (或者它在C#世界中有),因为为了使它有效,需要在调用链中一直支持它。强制异步执行同步操作可能会导致意外结果,因此您应该将其从原始方法一直扩展到使用它的顶级使用者。换句话说,如果您创建或使用使用它的类型,那么该类型也应该实现它,依此类推。所以是的,它预计会为每个依赖它的函数添加异步。但请注意,您不应该先行添加异步添加到不实际实现或需要它的函数。
试想:如果您使用async
(await
某事,我的意思是),您是async
。避免将async
调用压缩成同步的东西。
答案 1 :(得分:6)
我在很多地方都提出要求,我必须将所有这些功能标记为异步
是的,如果您的所有代码都是异步的,那么您可以在任何地方使用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));
}
*/
答案 2 :(得分:0)
找到a great answer here →'陷阱3:你的整个堆栈需要异步'
不,async/await
没有传染性。(我也相信同样的事情)
您可以随时将同步功能的结果视为承诺,并恢复正常。
来自developer.mozilla.org:
async函数声明定义了一个异步函数...
返回值 承诺将与价值一起解决 由异步函数返回,或被未捕获的异常拒绝 从异步函数中抛出。
示例代码:
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()
条款......很好,但不多于此。)