2016-09-19 4 views
-1

小さなノード& express.jsアプリケーションで作業しています。Node/Express.js:送信後にヘッダーを設定できない

throw new Error('Can\'t set headers after they are sent.'); 

が、私はそれらを個別に使用する場合は、http://localhost:3000/lastName/Smithに私が正しいを取得することができます:

res.render('employeeList',{data:employees.lookupByLastName(paramsLastName)}); 

それは常にres.format({...}); と競合するが、それは私にエラーを与えた: 私は私が使用している場合は、私のapp.get('/lastName/:lastName',(req,res) =>{...}); で見つかりましたビュー。私はres.format({...});を使用している場合、私はまたを通じて正しいAPIのフィードバックを得ることができます。

curl -X GET -H "Accept:application/xml" "http://localhost:3000/lastName/Smith" 

しかし、私は割り当ての要件と競合している、それらを同時に使用することはできません。 誰かに私に手がかりを与えることができますか?どうもありがとうございます!以下のコードを参照してください:

'use strict'; 
const express = require('express'); 
const _= require('underscore'); 
const handlebars = require('express-handlebars'); 
const employees = require('./employeeModule.js'); 
const bodyParser = require('body-parser'); 
const app = express(); 

app.engine('handlebars', 
    handlebars({defaultLayout: 'main'})); 

app.set('view engine', 'handlebars'); 

app.use(express.static(__dirname + '/public')); 
app.use(bodyParser.urlencoded({extended:false})); 
app.use(bodyParser.json()); 

// GET request to the homepage 
app.get('/', (req, res) => { 
    res.render('home'); 
}); 
app.get('/addEmployee',(req,res) => { 
    res.render('newEmployee'); 
}); 
//..........................Problem here......................... 
app.get('/id/:id',(req,res)=>{ 
    let paramsId = parseInt(req.params.id); 
    //res.render('employeeList',{data:employees.lookupById(paramsId)}); 
    //res.send(employees.lookupById(paramsId)); 
    res.format({ 
     'application/json':() => { 
      res.json(employees.lookupById(paramsId)); 
     }, 
     'application/xml':() => { 
      let employeeXml = 
       '<?xml version="1.0"?>\n<employees>\n' + 
       employees.lookupById(paramsId).map((e)=>{ 
        return ' <employee id="' + e.id + '">' + 
         '<firstName>' + e.firstName + '</firstName>'+ '<lastName>' + e.lastName + '</lastName>' + '</employee>'; 
       }).join('\n') + '\n</employees>\n'; 
      res.type('application/xml'); 
      res.send(employeeXml); 
     }, 
     'text/html':() => { 
      let employeeHtml = '<ul>\n' + 
       employees.lookupById(paramsId).map((e)=>{ 
        return ' <li>' + e.id + ' - ' + 
         e.firstName + ' - ' + e.lastName+'</li>'; 
       }).join('\n') + '\n</ul>\n'; 

      res.type('text/html'); 
      res.send(employeeHtml); 
     }, 
     'text/plain':() => { 
      let employeeText = 
       employees.lookupById(paramsId).map((e)=>{ 
        return e.id + ': ' + e.firstName + e.lastName; 
       }).join('\n') + '\n'; 
      res.type('text/plain'); 
      res.send(employeeText); 
     }, 
     'default':() => { 
      res.status(404); 
      res.send("<b>404 - Not Found</b>"); 
     } 
    }); 

}); 
//..........................Problem here......................... 
app.get('/lastName/:lastName',(req,res) =>{ 
    let paramsLastName = req.params.lastName; 
    res.render('employeeList',{data:employees.lookupByLastName(paramsLastName)}); 
    res.format({ 
     'application/json':() => { 
      res.json(employees.lookupByLastName(paramsLastName)); 
     }, 
     'application/xml':() => { 
      let employeeXml = 
       '<?xml version="1.0"?>\n<employees>\n' + 
       employees.lookupByLastName(paramsLastName).map((e)=>{ 
        return ' <employee id="' + e.id + '">' + 
         '<firstName>' + e.firstName + '</firstName>'+ '<lastName>' + e.lastName + '</lastName>' + '</employee>'; 
       }).join('\n') + '\n</employees>\n'; 
      res.type('application/xml'); 
      res.send(employeeXml); 
     }, 
     'text/html':() => { 
      let employeeHtml = '<ul>\n' + 
       employees.lookupByLastName(paramsLastName).map((e)=>{ 
        return ' <li>' + e.id + ' - ' + 
         e.firstName + ' - ' + e.lastName+'</li>'; 
       }).join('\n') + '\n</ul>\n'; 

      res.type('text/html'); 
      res.send(employeeHtml); 
     }, 
     'text/plain':() => { 
      let employeeText = 
       employees.lookupByLastName(paramsLastName).map((e)=>{ 
        return e.id + ': ' + e.firstName + e.lastName; 
       }).join('\n') + '\n'; 
      res.type('text/plain'); 
      res.send(employeeText); 
     }, 
     'default':() => { 
      res.status(404); 
      res.send("<b>404 - Not Found</b>"); 
     } 
    }); 
}); 

app.post('/data',function (req,res) { 
    let bodyData = req.body; 
    let bodyDataFirstName = bodyData.firstName; 
    let bodyDataLastName = bodyData.lastName; 
    employees.addEmployee(bodyDataFirstName,bodyDataLastName); 
    res.redirect('/lastName/'+bodyDataLastName); 
}) 
app.get('/api/employees',(req,res) =>{ 
    res.format({ 
     'application/json':() => { 
      res.json(employees.getAllEmployee()); 
     }, 
     'application/xml':() => { 
      let employeeXml = 
       '<?xml version="1.0"?>\n<employees>\n' + 
       employees.getAllEmployee().map((e)=>{ 
        return ' <employee id="' + e.id + '">' + 
         e.firstName + e.lastName + '</employee>'; 
       }).join('\n') + '\n</employees>\n'; 
      res.type('application/xml'); 
      res.send(employeeXml); 
     }, 
     'text/html':() => { 
      let employeeHtml = '<ul>\n' + 
       employees.getAllEmployee().map((e)=>{ 
        return ' <li>' + e.id + ' - ' + 
         e.firstName + ' - ' + e.lastName+'</li>'; 
       }).join('\n') + '\n</ul>\n'; 

      res.type('text/html'); 
      res.send(employeeHtml); 
     }, 
     'text/plain':() => { 
      let employeeText = 
       employees.getAllEmployee().map((e)=>{ 
        return e.id + ': ' + e.firstName + e.lastName; 
       }).join('\n') + '\n'; 
      res.type('text/plain'); 
      res.send(employeeText); 
     }, 
     'default':() => { 
      res.status(404); 
      res.send("<b>404 - Not Found</b>"); 
     } 
    }); 
}); 


app.use((req, res) => { 
    res.status(404); 
    res.render('404'); 
}); 


app.listen(3000,() => { 
    console.log('http://localhost:3000'); 
}); 


/* 
curl -X GET "http://localhost:3000/api/employees" 

curl -X GET -H "Accept:application/json" "http://localhost:3000/api/employees" 

curl -X GET -H "Accept:application/xml" "http://localhost:3000/api/employees" 

curl -X GET -H "Accept:text/html" "http://localhost:3000/api/employees" 

curl -X GET -H "Accept:text/plain" "http://localhost:3000/api/employees" 

*/ 
/* 
curl -X GET "http://localhost:3000/api/employees" 

curl -X GET -H "Accept:application/json" "http://localhost:3000/lastName/Smith" 
curl -X GET -H "Accept:application/xml" "http://localhost:3000/lastName/Smith" 

curl -X GET -H "Accept:application/json" "http://localhost:3000/id/2" 
curl -X GET -H "Accept:application/xml" "http://localhost:3000/id/2" 

*/ 

答えて

0

同じリクエストに対して2回応答を送信しています。

受信したエラーメッセージは、コードが同じ要求に対して2つの応答を送信しようとした場合に発生します。したがって、コード内のすべての場所が削除されなければなりません。

ハンドブックapp.get('/lastName/:lastName', ...)ハンドラでは、最初にres.render()を呼び出してから、res.send()を実行しようとしています。あなたは再びres.send()またはres.json()を呼び出すことはできませんので、それは同じ要求に別の応答を送信しようとすると、それがエラーをトリガするので、しかし、あなたはres.render()を呼んでいるようにして、要求に対する応答は、すでにその呼び出しによって送信されますメッセージが表示されます。

HTMLをレンダリングし、そのレンダリングされたHTMLを後で送信される応答の一部として使用する場合は、別の形式のres.render()を使用してコールバックを渡し、後で送ることができるHTMLを使用して戻ることができます。

コールバックオプションを使用してHTMLをフェッチして送信し、後で送信する応答を送信できるようにする方法については、docを参照してください。

一般的なスキームは、このようなものです:

app.get('/lastName/:lastName',(req,res) =>{ 
    res.render(file, options, function(err, html) { 
     if (!err) { 
      // response has not been sent yet 
      // put your res.format() code here and use the above html argument 
     } 
    }) 
}) 
+0

なぜdownvoteですか?これは明らかにOPのコードの問題です。 – jfriend00

0

あなたは二度、応答を送っています。

あなたres.renderemployeeListをレンダリングして、それを応答として送信します。その後、別の応答を送信しようとしています。これは許可されておらず、要求 - 応答サイクルに対応していません。また

、あなたがあなたのページをレンダリングするテンプレートエンジンを使用している:

let paramsLastName = req.params.lastName; 
res.render('employeeList',{data:employees.lookupByLastName(paramsLastName)}); 

、その後、あなたはここで手動でそれをやってみてください。

'text/html':() => { 
      let employeeHtml = '<ul>\n' + 
       employees.lookupById(paramsId).map((e)=>{ 
        return ' <li>' + e.id + ' - ' + 
         e.firstName + ' - ' + e.lastName+'</li>'; 
       }).join('\n') + '\n</ul>\n'; 

      res.type('text/html'); 
      res.send(employeeHtml); 
     } 

通話解像度のいずれかをすることができます。res.formatの内部に'text/html'、 またはres.formatブロックの外側にapp.renderを使用してレンダリングします。これはhtmlをレンダリングしますが、レスポンスとして送信しません。

app.render('index', {data:employees.lookupByLastName(paramsLastName)}, function(err, result) { 
    // result is the resulting html from rendering your data. 
    // save it to some variable to use later or do something with it here 
}); 
関連する問題