簡體   English   中英

Node.js用異步數據響應

[英]Node.js respond with asynchronous data

最近,我開始學習有關Node.js及其功能的一些知識,並嘗試將其用於某些Web服務。 我想創建一個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請求完成后將響應發布給用戶,但我找不到方法,因為我使用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.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", ..., ..., ...);

使用此系統,將根據我們使用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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM