将多个函数调用为promises get Error:发送后无法设置标头

时间:2017-05-31 16:21:05

标签: javascript node.js promise

我试着编写这段代码非常简单,专注于解决问题,但我真正想要的是一个nodejs控制器多次调用另一个更高级的nodejs控制器。

这是我的路线

// test Route
var express = require('express');
var router = express.Router();
var testController = require('../controllers/testController');

router.get('/getTest', function(req, res) {
    testController.getTest(req, res);
});

module.exports = router;

这是我的 testController.js

exports.getTest = function(req, res) {

    var myArray = [300,200,400,100,500];
    var myResult = [];


    // Find all data based on myArrau
    var findData = function() {
        return new Promise((resolve, reject) => {
        for (var i=0; i<myArray.length; i++) {
            callDataController(i, myArray[i]);
        }
        resolve();
    })};


    // Call and get the specific data
    var dataController = require('./dataController');
    var callDataController = function(i, myValue) {
        return new Promise((resolve, reject) => {
        dataController.getData (
            { "myValue": myValue }, res, 
            function(err, data) {
                if (!err) {
                    myResult[i] = data;  
                    resolve(data);
                } else {
                    reject(new Error('ERR dataController: ' + err));
                };
            });
    })};


    // Send result to page
    var sendResult = function(data) {
        return new Promise((resolve, reject) => {
            res.json({error:false, "myResult":myResult})
            resolve();
        });
    };


    // Run promises
    findData()
        .then(sendResult)
        .catch(err => {
            console.log("getTest ERR: " + err);
            res.json({error:true,err})
        }
    )
}

这是我的 dataController ,通常会做很多mongodb工作

exports.getData = function(req, res) {
    console.log("Data received: " + JSON.stringify(req, null, 4));

    console.log("Doing lots of mongodb work taking milliseconds to minutes")
    setTimeout(function(){},req.myValue);

    res.json({error:false,  "myValue":req.myValue+1000 })
 }

这就是问题所在,最好由终端console.log

解释
Data received: {
    "myValue": 300
}
Do a LOT of mongodb work taking anywhere from milliseconds to minutes
Data received: {
    "myValue": 200
}
Do a LOT of mongodb work taking anywhere from milliseconds to minutes
Data received: {
    "myValue": 400
}
Do a LOT of mongodb work taking anywhere from milliseconds to minutes
Data received: {
    "myValue": 100
}
Do a LOT of mongodb work taking anywhere from milliseconds to minutes
Data received: {
    "myValue": 500
}
Do a LOT of mongodb work taking anywhere from milliseconds to minutes
GET /testRoute/getTest 304 8.448 ms - -
getTest ERR: Error: Can't set headers after they are sent.
(node:9976) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): Error: Can't set headers after they are sent.
(node:9976) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 2): Error: Can't set headers after they are sent.
(node:9976) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 3): Error: Can't set headers after they are sent.
(node:9976) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 4): Error: Can't set headers after they are sent.
(node:9976) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 6): Error: Can't set headers after they are sent.

即使我只在myArray中放入一个值,我仍然会收到错误:发送后无法设置标题。

这是异步的一点,我无法开始工作。 (已经尝试将它们全部添加到Promise.all数组中,同样的问题)

1 个答案:

答案 0 :(得分:1)

您的问题是,您多次呼叫的控制器正在将响应写入客户端 - 多次(或至少,它正在尝试)。相反,让它只返回一个承诺,并仅在路由器代码中响应:

// test Route
var express = require('express');
var router = express.Router();
var testController = require('../controllers/testController');
router.get('/getTest', function(req, res) {
    testController.getTest(req).then(function sendResult(myResult) {
         res.json({error:false, "myResult":myResult}))
    }, err => {
        console.log("getTest ERR: " + err);
        res.json({error:true,err});
    });
});
module.exports = router;

// testController.js
var dataController = require('./dataController');
exports.getTest = function(req) {
    var myArray = [300,200,400,100,500];
    var myResult = [];

    // Find all data based on myArrau
    function findData() {
        return myArray.map(callDataController);
    }

    // Call and get the specific data
    function callDataController(myValue, i) {
        return dataController.getData (
            { "myValue": myValue }
        ).catch(function(err) {
            throw new Error('ERR dataController: ' + err)
        });
    };

    // Run promises
    return Promise.all(findData());
}

// dataController
exports.getData = function(req) {
    return new Promise((resolve, reject) => {
        console.log("Data received: " + JSON.stringify(req, null, 4));

        console.log("Doing lots of mongodb work taking milliseconds to minutes")
        setTimeout(function(){
            resolve({error:false, "myValue":req.myValue+1000 });
        }, req.myValue);
    });
};