Wednesday, 31 May 2017

Calling several functions as promises get Error: Can't set headers after they are sent

I tried to write this code very simple to focus on solving the problem, but what I really want is for one nodejs controller to call another more advanced nodejs controller multiple times.

This is my Route

// 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;

This is my 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})
        }
    )
}

And this is my dataController which usually do a lot of mongodb work

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 })
 }

And here comes the problem, best explained by the terminal 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.

Even if I only put one value in myArray I still get the Error: Can't set headers after they are sent.

This is the one point of async which I just cant get to work. (already tried adding them all to a Promise.all array, same problem)



via torbenrudgaard

No comments:

Post a Comment