Javascript 为什么';t';等待&x27;等待axios请求完成?

Javascript 为什么';t';等待&x27;等待axios请求完成?,javascript,json,asynchronous,async-await,axios,Javascript,Json,Asynchronous,Async Await,Axios,我试着用axios读取HTTP响应,用stream JSON在流模式下解析JSON,这样我就可以根据需要完全适应我的数据库。它工作得很好,但是如果我尝试关闭数据库连接一切都会崩溃,因为连接关闭得太快了。 问题是:wait并不等待extract_coins函数完成(即使它返回了承诺)并在最终作用域中关闭数据库连接 提取硬币: module.exports = async function extract_coins(url, emitter){ return await axios({

我试着用axios读取HTTP响应,用stream JSON在流模式下解析JSON,这样我就可以根据需要完全适应我的数据库。它工作得很好,但是如果我尝试关闭数据库连接一切都会崩溃,因为连接关闭得太快了。 问题是:wait并不等待extract_coins函数完成(即使它返回了承诺)并在最终作用域中关闭数据库连接

提取硬币:

module.exports = async function extract_coins(url, emitter){
    return await axios({
        method: 'get',
        url: url,
        responseType: 'stream'
    }).then((res) => {
        const pipeline = chain([
            res.data,
            parser(),
            pick({filter: 'data'}),
            streamArray()
        ]);
        pipeline.on('data', data => {
            emitter.emit('coin_extracted', data.value);
        });
        pipeline.on('end', () => console.log("All the coins were successfully passed!"));
    });
};

由于与异步
管道
相关的代码未被承诺,因此当前无法返回在获得“end”事件时解析的承诺

您的
wait
确实在等待承诺的解决,但是您的
然后
回调返回
未定义的
,因此在
结束
事件广播之前很久,它就解决了承诺

因此,改变这一点:

then((res) => {
    const pipeline = chain([
        res.data,
        parser(),
        pick({filter: 'data'}),
        streamArray()
    ]);
    pipeline.on('data', data => {
        emitter.emit('coin_extracted', data.value);
    });
    pipeline.on('end', () => console.log("All the coins were successfully passed!"));
});
为此:

then((res) => new Promise((resolve) => {
    const pipeline = chain([
        res.data,
        parser(),
        pick({filter: 'data'}),
        streamArray()
    ]);
    pipeline.on('data', data => {
        emitter.emit('coin_extracted', data.value);
    });
    pipeline.on('end', () => {
        console.log("All the coins were successfully passed!");
        resolve();
    });
}));

实际上,您使用了ES6+方式,但不是以常见方式,这会导致此问题,但肯定的是,在
旁边使用
wait
,然后使用
恰恰是一个错误,您应该像以下代码一样编写它们:

const main = async () => {
   try {
     const dbcfg = config.get('db.coins');
     const db = await coins_db_configure(dbcfg);
     console.log('Connected to the database and created coins table!');
     await extract_coins('some_url_which_gives_correct_json', coins_emitter);

   } catch (e) {
      console.error(e);

   } finally {
      await db.close();

   }
};

main();
如您所见,我将所有代码放在
try
块中,因为使用
async/await
意味着我们假装编写了一个同步代码,但实际上它是
async
,所以我们应该将所有代码,尤其是异步行放在
try
块中。将它们放入
try
块后,由于
()
JavaScript解释器后面的
async
标志等待每一行完成,如果每一行都有错误,下一行将不会运行,解释器将落入
catch
块,最终在所有情况下都会像现在一样运行

好的,现在回到主要问题,提取硬币功能:

export default (async function extract_coins(url, emitter) {
  try {
    const res = await axios({
      method: 'get',
      url: url,
      responseType: 'stream'
    });
    const pipeline = chain([
      res.data,
      parser(),
      pick({filter: 'data'}),
      streamArray()
    ]);
    await pipeline.on('data', data => {
      emitter.emit('coin_extracted', data.value);
    });
    await pipeline.on('end', () => console.log("All the coins were successfully passed!"));
    // HERE: return what you want

  } catch (e) {
    throw e;

  }

});
这就是问题的原因,您应该使用新的EcmaScript方法传递
extract\u coins
函数的承诺,而不是使用回调函数

如果我想在你的位置,我会像下面这样写
提取硬币

const extract_coins = async (url, emitter) => {
  try {
    const res = await axios({
      method: 'get',
      url: url,
      responseType: 'stream'
    });
    const pipeline = chain([
      res.data,
      parser(),
      pick({filter: 'data'}),
      streamArray()
    ]);
    await pipeline.on('data', data => {
      emitter.emit('coin_extracted', data.value);
    });
    await pipeline.on('end', () => console.log("All the coins were successfully passed!"));
    // HERE: return what you want

  } catch (e) {
    throw e;

  }

};

export default extract_coins;

提取函数中没有返回任何内容。管道中发生了异步事件,这些事件不是基于承诺的,因此不会等待。@Phix我返回承诺并希望等待理解“结束”-事件应该做出承诺fulfilled@trincot,就像你说的,我删除了我所有的评论。我也尝试了一些Promissipations和你的,但现在我得到了另一个错误:连接终止,提取硬币的执行速度非常慢。为什么它在不关闭数据库连接的情况下运行得如此快速和良好?如果您删除了
try/catch
,那么在哪一条语句中会出现错误?哪个console.log需要很长时间才能显示?您确定只调用一次
main
?但是,请注意,这里不是渐进式修复调试会话的场所。我想我已经回答了您的问题“为什么不等待axios请求完成?”我很乐意提供帮助,所以只需彻底调试以提供准确的信息。可能您需要问一个关于新问题的新问题…您是对的,但db.close()和extract_coins()都不会导致连接终止错误,当我想在回调中提示函数并解析它时,就会发生这种情况。一个小问题是,当您试图在try范围内使用它时,如何在try范围内定义
db
。我认为这是不正确的,因为
config.get()
函数会抛出异常,最后作用域将无法正常工作,因为
db
变量不存在。
const extract_coins = async (url, emitter) => {
  try {
    const res = await axios({
      method: 'get',
      url: url,
      responseType: 'stream'
    });
    const pipeline = chain([
      res.data,
      parser(),
      pick({filter: 'data'}),
      streamArray()
    ]);
    await pipeline.on('data', data => {
      emitter.emit('coin_extracted', data.value);
    });
    await pipeline.on('end', () => console.log("All the coins were successfully passed!"));
    // HERE: return what you want

  } catch (e) {
    throw e;

  }

};

export default extract_coins;