【问题标题】:Is there a synchronous function for jq?jq有同步功能吗?
【发布时间】:2019-10-21 10:06:41
【问题描述】:

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!")
});

【问题讨论】:

  • 您已经有一个.catch(),只需添加一个.then()
  • 所以我在 catch(....) 之后添加 .then() ?
  • 这就是你对 Promise 所做的事情。
  • 我在 catch 之后添加 .then() 但我什么也没得到,这是相同的结果,所以你要求我这样做:data = jq.run(filter, jsonPath).then((output) => { console.log(output) }).catch((err) => { console.error(err) }).then() 如果你要求我这样做它不起作用
  • 我不明白你能解释一下吗?

标签: javascript node.js json promise jq


【解决方案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 还返回一个承诺,您可以通过调用.then.catch 来附加更多回调。

在您的代码中,

data = jq.run(filter, jsonPath).then(...).catch(...)

data 只是另一个承诺,但其中没有任何有用的返回值(因为您的 thencatch 回调不返回任何值)。

要修正你的逻辑,它应该如下所示:

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 函数仍然返回一个承诺。

【讨论】:

    猜你喜欢
    • 2012-02-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多