Node.js响应asynchronous数据

最近我开始学习一些关于Node.js和它的function,并尝试将它用于一些Web服务。 我想创build一个Web服务,它将作为Web请求的代理。 我希望我的服务以这种方式工作:

  1. 用户将访问我的服务 – > http://myproxyservice.com/api/getuserinfo/tom
  2. 我的服务将执行请求 – > http://targetsite.com/user?name=tom
  3. 响应的数据会反映给用户。

为了实现它,我使用了下面的代码:

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请求完成时,我无法find如何这样做,因为我使用Express和Express使用asynchronous调用,所以做的HTTP请求。 我知道如果我想这样做,我应该传递makeProxyApiRequest响应对象,以便能够将它传递给callback,但由于asyn问题,这是不可能的。

有什么build议么? 帮助将不胜感激。

当你使用你的函数来处理你的路由处理请求时,最好把它们写成明确的中间件函数,采取特定的请求/响应对,并利用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 } ); 

更好的办法是将这些中间件function现在移到他们自己的文件中,所以你可以简单地做:

 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尽可能小。 请注意,客户端的浏览器将通过快速等待响应,发生一次res.writeres.jsonres.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", ..., ..., ...); 

使用这个系统,任何路由的:name部分将根据我们使用app.param定义的name参数来处理。 请注意,我们不需要多次定义这一点:我们可以执行以下操作,它将全部工作:

 app.post("/api/getuserinfo/:name", ..., ..., ...); app.post("/register/:name", ..., ..., ... ); app.get("/api/account/:name", ..., ..., ... ); 

并且对于每个path: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数据提取。