2012-07-04 27 views
11

Tôi muốn đạt được một cái gì đó như thế này:Làm thế nào để có một NodeJS/kết nối phần mềm trung gian thực hiện sau khi responde.end() đã được gọi?

var c = require('connect'); 
var app = c(); 

app.use("/api", function(req, res, next){ 
    console.log("request filter 1"); 
    next(); 
}); 

app.use("/api", function(req, res, next){ 
    console.log("request filter 2"); 
    next(); 
}); 

app.use("/api", function(req, res, next){ 
    console.log("request handler"); 
    res.end("hello"); 
    next(); 
}); 

app.use("/api", function(req, res, next){ 
    console.log("response post processor"); 
    next(); 
}); 
app.listen(3000); 

Khi tôi cuộn tròn cho địa chỉ, tôi nhận được một ngoại lệ đối với giao diện điều khiển phàn nàn về tiêu đề không thể bị làm phiền sau khi được gửi mà là công bằng đủ. Chỉ rằng tôi không chạm vào đối tượng phản hồi.

/usr/bin/node app2.js 
request filter 1 
request filter 2 
request handler 
Error: Can't set headers after they are sent. 
    at ServerResponse.OutgoingMessage.setHeader (http.js:644:11) 
    at ServerResponse.res.setHeader (/home/zpace/node_modules/connect/lib/patch.js:59:22) 
    at next (/home/zpace/node_modules/connect/lib/proto.js:153:13) 
    at Object.handle (/home/zpace/WebstormProjects/untitled1/app2.js:25:5) 
    at next (/home/zpace/node_modules/connect/lib/proto.js:190:15) 
    at Object.handle (/home/zpace/WebstormProjects/untitled1/app2.js:19:5) 
    at next (/home/zpace/node_modules/connect/lib/proto.js:190:15) 
    at Object.handle (/home/zpace/WebstormProjects/untitled1/app2.js:14:5) 
    at next (/home/zpace/node_modules/connect/lib/proto.js:190:15) 
    at Function.app.handle (/home/zpace/node_modules/connect/lib/proto.js:198:3) 

Gỡ rối lớp NodeJS/Connect tôi đã vào một phần nào đó ngụ ý rằng nếu tiêu đề đã được gửi sau đó thực hiện một handler tuyến đường phải khởi tạo tiêu đề phản ứng.

Câu hỏi đặt ra là nếu các hành vi nêu trên là có chủ ý (tức là thấy việc thi hành bất kỳ mã sau một handler tuyến đường đã hoàn tất việc gửi một phản ứng là một cái gì đó hoàn toàn không thể tưởng tượng hay chỉ đơn giản là một lỗi trong kết nối?

+0

Bạn đang thực hiện 'res.end (" hello ")' trong mã số –

+0

có. xử lý đáp ứng được thực hiện, đáp ứng đã sẵn sàng để được truyền đi. và bây giờ tôi muốn ví dụ đặt một bản ghi hoặc dọn dẹp một cái gì đó. –

+0

Bạn đã tìm ra cách để làm điều đó vì bạn đã hỏi câu hỏi này chưa? Có vẻ như không có phản ứng về chủ đề này và tôi đang cố gắng hiểu tại sao nhóm Connect thực hiện mọi thứ theo cách họ đã làm. – conradkdotcom

Trả lời

24

Không chắc bạn có tìm thấy giải pháp của mình hay không.

Nếu bạn muốn thiết kế bộ xử lý sau cho chu kỳ yêu cầu, bạn có thể sử dụng phần mềm trung gian lắng nghe sự kiện "kết thúc" trên đối tượng phản hồi. Như thế này:

app.use(function(req, res, next){ 
    res.on('finish', function(){ 
    console.log("Finished " + res.headersSent); // for example 
    console.log("Finished " + res.statusCode); // for example 
    // Do whatever you want 
    }); 
    next(); 
}); 

Chức năng gắn liền với sự kiện "kết thúc" sẽ được thực hiện sau khi phản ứng được viết ra (có nghĩa là NodeJS đã trao tắt tiêu đề phản ứng và cơ thể cho hệ điều hành cho mạng truyền dẫn).

Tôi đoán đây phải là những gì bạn muốn.

+0

đây là ... cảm ơn! –

+2

sự kiện 'kết thúc' không được kích hoạt trong trường hợp đối tượng phản hồi đã kích hoạt sự kiện' close' - nó xảy ra khi socket được đóng trước khi một phản hồi có thể được gửi đi. Nếu bạn muốn nắm bắt thời điểm chu trình yêu cầu/phản hồi kết thúc (ngay cả khi một phần mềm trung gian xử lý lỗi gửi phản hồi) có thể tốt hơn là ghi đè hàm 'cuối' của phản hồi: ' var _end = res .kết thúc; res.end = function() { console.log ('cuối cùng của phản hồi'); _end.apply (điều này, đối số); } ' – godness

+0

@godness ý tưởng hay. cảm ơn. – r3wt

2

Tôi nghĩ Đây là một vấn đề quy hoạch xấu Bạn nên giải quyết vấn đề này một cách tốt hơn Tôi không biết tại sao bạn có một trình xử lý yêu cầu và một bộ xử lý yêu cầu riêng biệt, nhưng hãy tìm hiểu xem chúng tôi có thể làm gì. đã kết thúc, bạn không thể đọc lại tiêu đề.

Vì vậy, không hoàn thành phản hồi đến khi bộ xử lý bài được gọi.

var isEnd; 

app.use("/*", function(req, res, next){ 
    isEnd = false; 
}) 

app.use("/api", function(req, res, next){ 
    console.log("request handler"); 
    res.write("hello"); 
    isEnd = true; 
    next(); 
}); 

app.use("/api", function(req, res, next){ 
    console.log("response post processor"); 
    if(isEnd) { 
     res.end(); 
    } 
    else next(); 
}); 

Đây là một giải pháp, nhưng điều này có thể không tốt nhất cho vấn đề của bạn.

Theo ý kiến ​​của tôi, điều đó thực sự tồi tệ khi bạn gọi next() sau khi câu trả lời đã hoàn tất. Nếu bạn cần một bộ xử lý bài đăng, tại sao bạn làm điều đó trong bộ lọc yêu cầu (hoặc cái này là gì). Gọi một hàm nhưng không next()

Có lẽ đây:

app.use("/api", function(req, res, next){ 
    console.log("request handler"); 
    res.end("hello"); 
    setTimeout(function(){(postProcessor(req)},0); 
}); 

function postProcessor(req) { 
//doing post process stuff. 
//response not needed because already ended. 
} 

Hoặc này:

app.use("/api", function(req, res, next){ 
    console.log("request handler"); 
    res.writed("hello"); 
    setTimeout(function(){(postProcessor(req)},0); 
    // u cant res.end here because setTimeout. 
    //If you dont use setTimeout you can use res.end here, but not bot function. 
}); 

function postProcessor(req, res) { 
//doing post process stuff. 
res.end(); 
} 

Các next() không phải dành cho việc sử dụng đó, những gì bạn sử dụng.

Tôi hy vọng câu trả lời của tôi sẽ giúp bạn, nhưng tôi biết nó không bao gồm mọi thứ, nhưng câu trả lời của bạn cũng không thực sự cụ thể.

+0

Hãy xem xét rằng các nút nodejs/kết nối được dân cư với logic hỗn hợp từ các nguồn khác nhau: A) mã đại diện cho logic nghiệp vụ và B) mã đại diện cho cơ sở hạ tầng. Vì vậy, nếu hai ppl khác nhau tạo ra các bộ phận kinh doanh và cơ sở hạ tầng thì có thể không có sự hợp tác phát triển chức năng hợp tác/mạnh mẽ ở đây. Anh chàng logic kinh doanh phải xử lý những thứ như anh ta đang chạy một mình (không biết về cơ sở hạ tầng), mã cơ sở hạ tầng cần giống nhau: là bất khả tri đối với mã lớp kinh doanh. –

+0

Và một lần nữa: trong funciton cuối cùng ("bộ xử lý bài") Tôi không chạm vào các tiêu đề, các vật thể bất kỳ thứ gì đã bị đóng băng. –

1

Câu hỏi hay là thử làm việc với cà phê buổi sáng của bạn!

Vì vậy, hãy xem qua proto.js, nếu bạn có một cái nhìn xuống dòng 102 là app.handle là mã trình xử lý cho ngăn xếp phần mềm trung gian, bạn sẽ thấy cách next() hoạt động.

Trong trường hợp hàm next() được gọi, bạn có thể thấy nó kiểm tra xem res.headerSent có đúng hay không và nếu có thì nó sẽ phát ra lỗi.

Nếu dòng Modify 14:

app.use("/api", function(req, res, next){ 
    console.log("request handler"); 
    res.end("hello"); 
    console.log(res); 
    next(); 
}); 

Bạn sẽ thấy rằng nó thực sự đặt "headersSent" true. Vì vậy, sau khi chúng tôi đã kết thúc yêu cầu, bạn có thể thấy từ mã() tiếp theo mà nó ném lỗi vì các điều kiện được thảo luận.

+0

có, nhưng việc gửi yêu cầu không nhất thiết có nghĩa là chúng tôi đã kết thúc với chu kỳ yêu cầu. IMHO chỉ là một cách tiếp cận có thể có của nó. –