在Express服务器的app.get中进行异步调用

3
我正在制作一个Express服务器,将YouTube播放列表中的视频转换为XML播客。我的app.get返回一些生成的xml:
app.get("/", function(req, res) {
    res.set('Content-Type', 'text/xml');
    return res.send(xml(myXmlContent, { declaration: true }));
})

我需要填充myXmlContent并包括YouTube播放列表中的视频ID等数据。我可以使用YouTube API获取这些视频ID,但它是异步的。它在回调函数中返回ID。
我应该如何等到获取结果后再从app.get返回?我可能走错了路,因为超时可能成问题。有什么建议可以实现依赖于异步调用的动态XML生成吗?
2个回答

10

如何在从app.get()返回之前等待获取结果?

你不能在Javascript中“等待”。相反,当你从另一个API调用中获得结果时,在回调函数中发送响应。这是在node.js中异步开发的工作方式。

如何在从app.get()返回之前等待获取结果?

你不需要等待。在发送响应之前,可以从app.get()正常返回。但这并不意味着你已经完成所有处理了。app.get()(和express中间件)旨在让你可以使用异步操作来获取响应数据。你只需要返回,然后稍后在异步操作完成并且你获取到所需的数据时,再发送响应。

“我可能做法不对,因为超时可能会成为问题。”

这不是错误的方法。但是,如果你的外部API真的很慢,那么你可能需要担心Express的超时或浏览器的超时。你可以配置Express超时,但处理浏览器超时就没有那么容易了。如果获取结果需要时间太长,以至于达到了浏览器超时时间,那么你可能需要重新考虑你的方法,因为普通用户在等待超过浏览器超时时间后,无论如何都会放弃页面请求或按钮操作。

获取数据后发送数据的几个选项。由于你没有展示你使用的外部API及其工作方式,因此我们无法提供具体的建议。但通常有以下几种方法:

  1. res.send()放置在另一个API异步完成回调函数中。
  2. 将其他操作的结果导入响应中。
  3. 使用承诺(Promise)可以通知你另一个API尚未完成,然后将res.send()放置在Promise的.then()处理程序中。
例如:

const rp = require('request-promise');

app.get("/", function(req, res) {
    rp(someURL).then(result => {
        // do some processing of result into finalData
        res.send(finalData);
    }).catch(err => {
        console.log(err);
        res.sendStatus(501);
    });
});

非常好。不确定为什么我一直认为你必须在返回语句中使用res.send调用(即“return res.send(finalData)”),但正如你所解释的那样,它对我很有效。谢谢! - Mike Miller
1
@MikeMiller - 当你想要退出函数并防止其后运行其他代码时,才会使用return res.send()。我的示例不需要这样做,因为res.send()已经是最后一行要执行的代码了。express不会关注请求处理程序的任何返回值,因此没有必要返回任何内容。return res.send()只是根据代码流程控制需要而进行的操作。 - jfriend00

-1
你可以使用async和await来完成这个任务。
app.post('/page', async(req, res) => {
  const content = await mycontent //result you are waiting for
  res.send(content)
});

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接