[英]Node.js respond with asynchronous data
最近,我開始學習有關Node.js及其功能的一些知識,並嘗試將其用於某些Web服務。 我想創建一個Web服務,它將充當Web請求的代理。 我希望我的服務可以這樣工作:
為了實現它,我使用了以下代碼:
app.js:
var express = require('express');
var bodyParser = require('body-parser');
var app = express();
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
var proxy = require('./proxy_query.js')
function makeProxyApiRequest(name) {
return proxy.getUserData(name, parseProxyApiRequest);
}
function parseProxyApiRequest(data) {
returned_data = JSON.parse(data);
if (returned_data.error) {
console.log('An eror has occoured. details: ' + JSON.stringify(returned_data));
returned_data = '';
}
return JSON.stringify(returned_data);
}
app.post('/api/getuserinfo/tom', function(request, response) {
makeProxyApiRequest('tom', response);
//response.end(result);
});
var port = 7331;
proxy_query.js:
var https = require('https');
var callback = undefined;
var options = {
host: 'targetsite.com',
port: 443,
method: 'GET',
};
function resultHandlerCallback(result) {
var buffer = '';
result.setEncoding('utf8');
result.on('data', function(chunk){
buffer += chunk;
});
result.on('end', function(){
if (callback) {
callback(buffer);
}
});
}
exports.getUserData = function(name, user_callback) {
callback = user_callback
options['path'] = user + '?name=' + name;
var request = https.get(options, resultHandlerCallback);
request.on('error', function(e){
console.log('error from proxy_query:getUserData: ' + e.message)
});
request.end();
}
app.listen(port);
我希望我不要搞砸這段代碼,因為我替換了一些適合我的示例的東西。
無論如何,問題是我想在HTTP請求完成后將響應發布給用戶,但我找不到方法,因為我使用express,而express使用異步調用,所以http請求也是如此。 我知道如果我想這樣做,我應該將makeProxyApiRequest傳遞給響應對象,這樣他就可以將其傳遞給回調,但是由於異步問題,這是不可能的。
有什么建議么? 幫助將不勝感激。
當您使用函數來處理路由處理中的請求時,最好將它們編寫為Express中間件函數,采用特定的請求/響應對,並使用Express的next
級聯模型:
function makeProxyApiRequest(req, res, next) {
var name = parseProxyApiRequest(req.name);
res.locals.userdata = proxy.getUserData(name);
next();
}
function parseProxyApiRequest(req, res, next) {
try {
// remember that JSON.parse will throw if it fails!
data = JSON.parse(res.locals.userdata);
if (data .error) {
next('An eror has occoured. details: ' + JSON.stringify(data));
}
res.locals.proxyData = data;
next();
}
catch (e) { next("could not parse user data JSON."); }
}
app.post('/api/getuserinfo/tom',
makeProxyApiRequest,
parseProxyApiRequest,
function(req, res) {
// res.write or res.json or res.render or
// something, with this specific request's
// data that we stored in res.locals.proxyData
}
);
現在最好將這些中間件功能移動到它們自己的文件中,因此您只需執行以下操作:
var middleware = require("./lib/proxy_middleware");
app.post('/api/getuserinfo/tom',
middleware.makeProxyApiRequest,
middleware.parseProxyApiRequest,
function(req, res) {
// res.write or res.json or res.render or
// something, with this specific request's
// data that we stored in res.locals.proxyData
}
);
並保持您的app.js盡可能小。 請注意,客戶端的瀏覽器將僅通過express等待響應,這將在使用res.write
, res.json
或res.render
等之后發生。 在此之前,瀏覽器和服務器之間的連接一直保持打開狀態,因此,如果您的中間件調用花費很長時間,那很好-瀏覽器將很樂意等待很長時間,以便將響應發送回去,並且還會做其他事情同時。
現在,為了獲得name
,我們可以使用express的參數構造:
app.param("name", function(req, res, next, value) {
req.params.name = value;
// do something if we need to here, like verify it's a legal name, etc.
// for instance:
var isvalidname = validator.checkValidName(name);
if(!isvalidname) { return next("Username not valid"); }
next();
});
...
app.post("/api/getuserinfo/:name", ..., ..., ...);
使用此系統,將根據我們使用app.param定義的name
參數來處理任何路由的:name
部分。 請注意,我們不需要多次定義:我們可以執行以下操作,並且都可以正常工作:
app.post("/api/getuserinfo/:name", ..., ..., ...);
app.post("/register/:name", ..., ..., ... );
app.get("/api/account/:name", ..., ..., ... );
對於帶有:name的每條路線,“ name”參數處理程序的代碼都會加入。
至於proxy_query.js
文件,將其重寫為適當的模塊可能比使用單個導出更安全:
// let's not do more work than we need: http://npmjs.org/package/request
// is way easier than rolling our own URL fetcher. In Node.js the idea is
// to write as little as possible, relying on npmjs.org to find you all
// the components that you need to glue together. If you're writing more
// than just the glue, you're *probably* doing more than you need to.
var request = require("request");
module.exports = {
getURL: function(name, url, callback) {
request.get(url, function(err, result) {
if(err) return callback(err);
// do whatever processing you need to do to result:
var processedResult = ....
callback(false, processedResult);
});
}
};
然后我們可以將其用作proxy = require("./lib/proxy_query");
在中間件中,我們實際上需要進行URL數據獲取。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.