【问题标题】:ExpressJS 4 execute function after res.send()ExpressJS 4 在 res.send() 之后执行函数
【发布时间】:2015-03-05 02:15:17
【问题描述】:

我是 nodeJS 和异步编程的新手。我使用 express 作为我的应用程序的基础,实际上只有一个路由服务于页面并接受来自表单的上传。上传文件后,我想向外部服务发出 POST 请求。尝试在 res.send(200) 之后执行任何代码会导致错误消息 Error: Can't set headers after they are sent.

我正在使用request 包将帖子发布到外部服务。

var express = require('express');
var router = express.Router();
var util = require("util");
var request = require("request");

/* POST uploads. */
router.post('/', function(req, res, next) {
    console.log("LOG:" + util.inspect(req.files));
    res.send('respond with a resource');
    postFile(req.files.file.path);
});

var postFile = function(path) {
    var opts = {
        method: 'POST',
        uri: 'https://example.com/api/files.upload',
        formData: {
            token: "xxx",
            file: fs.createReadStream(req.files.file.path)
        }
    }

    // console.log("LOG:\n" + util.inspect(opts));

    request.post(opts, function(error, response, body) {
        if (error) {
            console.log("ERROR LOG: " + util.inspect(error));
        } else {
            console.log("RESPONSE LOG:" + util.inspect(response));
        }
    });
}

module.exports = router;

postFile 函数本身可以正常工作,甚至在 res.send 之后直接添加 console.log 也会导致相同的错误。响应发送到客户端后,如何继续在服务器上执行代码?

从节点输出日志:

POST /uploads 200 85.201 ms - 23 Error: Can't set headers after they are sent. at ServerResponse.OutgoingMessage.setHeader (_http_outgoing.js:335:11) at ServerResponse.header (/Users/jason/dev/test/file-share/node_modules/express/lib/response.js:700:10) at ServerResponse.send (/Users/jason/dev/test/file-share/node_modules/express/lib/response.js:154:12) at fn (/Users/jason/dev/test/file-share/node_modules/express/lib/response.js:934:10) at View.exports.renderFile [as engine] (/Users/jason/dev/test/file-share/node_modules/jade/lib/index.js:374:12) at View.render (/Users/jason/dev/test/file-share/node_modules/express/lib/view.js:93:8) at EventEmitter.app.render (/Users/jason/dev/test/file-share/node_modules/express/lib/application.js:566:10) at ServerResponse.res.render (/Users/jason/dev/test/file-share/node_modules/express/lib/response.js:938:7) at /Users/jason/dev/test/file-share/app.js:58:7 at Layer.handle_error (/Users/jason/dev/test/file-share/node_modules/express/lib/router/layer.js:58:5)

【问题讨论】:

  • 一个编程错误是postFile() 应该使用传递给它的path 参数,而不是req.files.file.path。可能不是您的问题的原因。
  • 如果查看堆栈跟踪,它来自handle_error,这意味着 express 捕获到错误并尝试发送错误响应。 @jfriend00 提到的req.files.file.path 错误很可能导致函数抛出,所以你的res.send 发送并关闭连接,然后语法错误尝试发送错误页面。注释掉res.send,你会看到实际的错误。

标签: node.js express express-4


【解决方案1】:

下面的代码没有错,你可以在响应请求后执行代码。您只是不能再次发送标头。

router.post('/', function(req, res, next) {
  console.log("LOG:" + util.inspect(req.files));
  res.send('respond with a resource');
  postFile(req.files.file.path);
});

除非您愿意,否则使用 request POST 或 GET 不会响应您的请求。

【讨论】:

  • 我也这么认为,但事实仍然是即使在 res.send 之后使用 console.log 也会返回相同的错误。可能是我以某种方式错误地设置了我的项目。
  • 可能此错误消息来自您代码的另一部分。
  • 除此之外什么也不做。它接受一个文件并尝试上传它。删除 postFile(req.files.file.path);在 res.send() 并且代码工作正常之后,添加 console.log('test');在 res.send() 之后并产生相同的错误消息。
【解决方案2】:

您的postFile() 函数在此行中引用req.files.file.path

file: fs.createReadStream(req.files.file.path)

但是req 对象没有被传递给它。这应该会产生某种异常。

看来你应该只使用:

file: fs.createReadStream(path)

因为您将路径传递给postFile(path)

【讨论】:

  • 感谢您指出这一点,当我认为这可能只是一个愚蠢的错误时,我很兴奋。但是,改变它不会改变响应。完全删除调用并用简单的 console.log 替换它不会改变响应。
猜你喜欢
  • 1970-01-01
  • 2021-08-14
  • 2013-04-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多