【问题标题】:How to make a synchronous http request on a node server?如何在节点服务器上发出同步 http 请求?
【发布时间】:2019-12-21 11:17:15
【问题描述】:

我有一个带有多个 api 端点的节点 web 服务器。其中一个端点需要向另一台服务器发出请求,以便组装自己的响应。我已经看到了一些不同的答案,其中包含指向允许纯同步 Web 请求的库的链接,但它们都与表示不要在生产中使用它们的警告相关联。

这是我的服务器请求处理程序的示例:

app.get('/my_api_endpoint', function (req, res) {

    // Need to get data from other webservice using data 
    // from this request.
    data = request_to_other_web_service(req.params.some_value);

    res.status(200);
    res.send("This is the " + data);
    res.end();

});

是否有处理此类请求的标准模式?

【问题讨论】:

  • checkout axios,是一个基于promise的javascript http客户端。
  • 任何 node.js 服务器都不应该在任何实时请求处理程序中进行同步 I/O。绝不。它绝对会破坏服务器的可扩展性。相反,学习如何正确地进行异步 I/O。为了让我们向您展示如何向其他网络服务发出此请求,您必须向我们展示该请求的详细信息,然后我们才能向您展示如何正确执行此请求的具体细节。
  • 就目前而言,您要求的是 node.js 不适合做的事情,也不应该从任何 node.js 请求处理程序中完成。因此,需要重新表述问题以表达您要解决的问题,而不是您似乎想要的特定解决方案(同步 I/O)。这不是解决方案的正确方向。您发布的是XY problem,您在其中询问了有关您提出的解决方案方向的问题,而不是要求我们帮助您解决实际问题。
  • @jfriend00 也许同步是错误的词。我的意思是,在我制定来自我的 Web 服务的响应之前,我需要来自其他 Web 服务的响应。我认为我不需要提供其他请求的任何详细信息,除了它是标准的 http 请求和我的 web 服务需要工作的 json 响应。目前还不清楚为什么同步 I/O 如此糟糕(考虑到许多其他框架和语言在其 Web 框架中使用同步 I/O)。即使评估在技术上是“异步的”,它仍然需要阻止我的响应,直到它完成。
  • 嗯,你说的是“同步”。这显然是错误的词,因为这就是我的反应。你不需要任何东西来阻止。您只需在异步回调中完成响应。没有任何阻挡。没有同步网络。您只需要学习如何在 node.js 中使用异步 I/O 进行编程,您可以在其中处理回调中的响应。您可以使用常规异步回调,也可以使用 Promise 接口。在这两者中,您都在处理响应和任何想要在回调中使用它的代码。这就是你需要在 node.js/Javascript 中学习的内容。

标签: javascript node.js typescript express http


【解决方案1】:

尝试同步调用 HTTP 请求时收到错误/警告的原因是,从一开始,node.js 就采用回调和事件循环的核心理念构建。如果您尝试以同步方式编写异步代码......我可以为您指出异步/等待的方向。你可以用npm install node-fetch

const fetch = require('node-fetch');

app.get('/my_api_endpoint', async function (req, res) {

    // Need to get data from other webservice using data 
    // from this request.
    data = await fetch("http://...");

    res.status(200);
    res.send("This is the " + data);
    res.end();

});

【讨论】:

  • 是的,这正是我所需要的。我使用了 axios,但 async/await 语法有效。
【解决方案2】:

一般来说,所有 javascript 库/框架都对非同步操作很友好。那些不是将被社区忽略。 Express 已经允许您执行异步操作。

你有没有想过为什么 express 要求你通过调用 res 上的方法而不是简单地返回来“返回”响应?:

// frameworks in some other languages:

@Path("/my_api_endpoint")
Response myEndpoint() {
    data = request_to_other_web_service(some_value);
    return data; // Javascript frameworks don't use returns!!
}

这是因为所有的 javascript web 框架都是异步友好的。您使用回调(您稍后回调的函数)从路由返回的原因是因为您可以在其他函数中调用函数。在 Express 中,您调用 res.send() 在您已经执行了异步操作。具体操作方式取决于您使用的 API:

接受回调的 API:

app.get('/my_api_endpoint', function (req, res, next) {
    request(req.params.some_value, function (error, data) {
        if (!error) {
            res.status(200);
            res.send("This is the " + data);
        }
        else {
            next(error);
        }
    }
});

返回承诺的 API:

app.get('/my_api_endpoint', function (req, res, next) {
    request(req.params.some_value)
        .then(function (data) {
            res.status(200);
            res.send("This is the " + data);
        })
        .catch(function (error) {
            next(error);
        });
});

将 async/await 与返回承诺的 API 一起使用:

app.get('/my_api_endpoint', async function (req, res, next) {
    try {
        let data = await request(req.params.some_value)
        res.status(200);
        res.send("This is the " + data);
    }
    catch (error) {
        next(error);
    }
});

基于流的 API:

app.get('/my_api_endpoint', async function (req, res, next) {
    let dataStream = request(req.params.some_value);
    let buffer = "";

    dataStream.on('data', function (data) {
        buffer += data.toString('utf8');
    });

    dataStream.on('end', function () {
        res.status(200);
        res.send("This is the " + buffer);
    });

    dataStream.on('error', function () {
        next("Stream error");
    });

});

Express 可以处理任何异步程序流。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-10-29
    • 2015-07-18
    • 1970-01-01
    • 2018-01-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-10
    相关资源
    最近更新 更多