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