jq.run('.', '/path/to/file.json').then(console.log)
是异步的,因此当我尝试使用它时,得到以下信息:Promise { <pending> }
然后得到了结果,但是为时已晚...那么如何解决这个问题?
我尝试等待await
,但是我不知道该放在哪里。所以这是我的代码:
const jq = require('node-jq')
const filter = '[.root[].A[].AT]'
const jsonPath = './simple.json'
data = jq.run(filter, jsonPath).then((output) => {
console.log(output)
}).catch((err) => {
console.error(err)
})
fs.appendFile('./jqTest.txt', data + "\r\n", function (err) {
if (err) throw err;
console.log("complete!")
});
答案 0 :(得分:1)
异步API的全部要点是您不能编写
data = getResultsAsynchronously();
doStuffWith(data);
...
(除非您使用await
,这有点神奇。)
相反,传统的异步API在结果准备好时会调用一个函数:
getResultsAsynchronously(function (data) {
doStuffWith(data);
...
});
即而是将同步版本中原始函数调用之后的所有代码放入回调函数中,并传递给getResultsAsynchronously
。
Promise仍然遵循此一般模式,但是让您将启动异步操作本身与决定如何处理结果分离开来。也就是说,您可以首先在第二步中启动异步操作,然后注册一个回调,以便稍后处理结果:
promise = getResultsAsynchronously();
// and later:
promise.then(function (data) {
doStuffWith(data);
...
});
但是,如果您不想这样做,则不必将两个步骤分开:
getResultsAsynchronously().then(function (data) {
doStuffWith(data);
...
});
.then
还返回一个promise,您可以通过调用.then
或.catch
附加附加的回调。
在您的代码中,
data = jq.run(filter, jsonPath).then(...).catch(...)
data
只是另一个承诺,但其中没有任何有用的返回值(因为您的then
和catch
回调不返回任何值)。
要修正您的逻辑,它应如下所示:
jq.run(filter, jsonPath).then((data) => {
fs.appendFile('./jqTest.txt', data + "\r\n", (err) => {
if (err) throw err;
console.log("complete!")
});
}).catch((err) => {
console.error(err)
});
回顾一下:异步结果仅在回调函数中可用。您不能像同步操作一样使用返回值。
也就是说,async
/ await
使您可以将异步代码转换为同步代码(或至少看起来是同步的代码)。但是,此技巧仅在“内部”起作用:外部接口仍是异步的,您可以在内部编写更普通的代码。
例如:
// await is only available inside async functions, so let's define one:
(async function () {
// magic happens here:
let data = await jq.run(filter, jsonPath);
fs.appendFile('./jqTest.txt', data + "\r\n", (err) => {
if (err) throw err;
console.log("complete!")
});
})(); // ... and invoke it immediately
在内部,JavaScript会重写
x = await f();
doStuffWith(x);
...
变成看起来像
的东西return f().then((x) => {
doStuffWith(x);
...
});
即await
使您可以将回调函数的内容提取为直线代码。最终,整个async
函数仍然返回一个promise。