use*_*885 3 javascript ajax asynchronous node.js async-await
我来自PHP背景,我正在尝试学习NodeJS.
我知道Node中的所有内容都是异步的,但我发现我在代码中一直使用async/await组合,并且我想确保我没有做一些愚蠢的事情.
原因是我有很多情况需要在继续之前得到某些结果(例如,对于一个小的ajax请求).这个小的ajax请求没有别的目的,除了做我想要它的东西以及我指定的顺序,所以即使我做"异步方式"并使用回调写它我仍然有等待事情以正确的顺序完成.
现在每当我发现自己处于这种情况时,我只是等待等待结果:
即:
var result = await this.doSomething(data);
Run Code Online (Sandbox Code Playgroud)
反对使用回调
this.doSomething(data, function(callback) {
// code
callback();
});
Run Code Online (Sandbox Code Playgroud)
对我来说,第一个例子比第二个例子更清晰,这就是为什么我一直在选择它.但是我担心我可能会遗漏一些基本的东西.但是在异步调用下没有其他任何东西要处理的情况下,事情进展的唯一方法就是它遵循同步风格,在第二种风格中使用第一种风格有什么问题吗?
但是我担心我可能会遗漏一些基本的东西.
不,你不是,这正是你想要做的,假设this.doSomething(data)是异步的(如果它是一个ajax调用,人们希望它是异步的)并且它返回一个promise(所有用async关键字定义的函数都是隐含的).(如果它不是异步的,你不需要它await,尽管它是允许的.)
事情正在经历一个过渡,你可能有点困惑(可以理解).直到最近,Node API(内置的和第三方模块提供的)的压倒性惯例是使用"节点回调"模式,这是一个将进行异步工作的函数,它的最后一个参数是一个回调函数,它将调用第一个参数指示成功/失败(null=成功,其他任何东西是一个错误对象),后续参数提供结果.(你的第二个例子假设doSomething是其中之一,而不是一个返回一个promise的函数.)
示例:fs.readFile,您使用如下:
fs.readFile("/some/file", "utf-8", function(err, data) {
if (err) {
// ...handle the fact an error occurred..
return;
}
// ...use the data...
});
Run Code Online (Sandbox Code Playgroud)
然而,这种风格很快导致回调地狱,这是承诺(又名"期货")被发明的原因之一.
但是很多 Node API仍然使用旧模式.
如果需要使用"节点回调" - 模式函数,则可以使用util.promisify它们创建启用许可的版本.例如,假设您需要使用fs.readFile,它使用Node回调模式.您可以获得这样的承诺版本:
const readFilePromise = util.promisify(fs.readFile);
Run Code Online (Sandbox Code Playgroud)
...然后将其与async/ awaitsyntax一起使用(或直接使用promise then):
const data = await readFilePromise("/some/file", "utf-8");
Run Code Online (Sandbox Code Playgroud)
还有一个npm名为的模块promisify可以提供整个API的承诺版本.(可能不止一个.)
仅仅因为在大多数情况下promises和async/ await替换旧的Node回调样式并不意味着回调仍然没有位置:Promise只能解决一次.他们是一次性的事情.所以回调仍然有一个地方,比如使用EventEmitters的on方法,就像一个可读的流:
fs.createReadStream("/some/file", "utf-8")
.on("data", chunk => {
// ...do something with the chunk of data...
})
.on("end", () => {
// ...do something with the fact the end of the stream was reached...
});
Run Code Online (Sandbox Code Playgroud)
由于data会多次触发,因此使用回调是有意义的; 承诺不适用.
另请注意,您只能await在async函数中使用.因此,您可能会发现自己习惯于"主要"模块结构,看起来像这样:
// ...Setup (`require` calls, `import` once it's supported, etc.)...
(async () => {
// Code that can use `await `here...
})().catch(err => {
// Handle the fact an error/promise rejection occurred in the top level of your code
});
Run Code Online (Sandbox Code Playgroud)
catch如果您希望脚本以未处理的错误/拒绝终止,您可以将其关闭.(Node还没有这样做,但是一旦未处理的拒绝检测成熟了.)
或者,如果要在非async函数中使用启用promise的函数,只需使用then和catch:
this.doSomething()
.then(result => {
// Use result
})
.catch(err => {
// Handle error
});
Run Code Online (Sandbox Code Playgroud)
注意:节点7.x及更高版本中直接支持async/ await.如果您打算使用async/,请确保您的目标生产环境支持Node 7.x或更高版本await.如果没有,您可以使用像Babel这样的东西来转换代码,然后在旧版本的Node上使用转换后的结果.
| 归档时间: |
|
| 查看次数: |
470 次 |
| 最近记录: |