2016-04-13 20 views
2

Uygulamam için toplu API'yi uygulamaya çalışıyorum ve istemci sunucuya bir dizi istek gönderebilir ve tek bir yanıt bekleyebilir.NodeJS Express çerçevesindeki Toplu İşlem REST API istekleri işleniyor

MEAN yığın uygulamasında Express çerçevesini kullanma. Bunu istemciden alan bir toplu API kaynağı oluşturdum ve isteğin her bölümünde belirtilen URL'ye göre hareket etmeliyim.

Numune Talebi Gövde:

{ 
    "batchID": "abc123", 
    "batchReq": [{ 
     "id": "1", 
     "url": "/api/schoolm/students", 
     "method": "GET", 
     "value": null 
    }, { 
     "id": "2", 
     "url": "/api/schoolm/teachers", 
     "method": "POST", 
     "value": { 
      "name": "Teacher1", 
      "age": 34 
     } 
    }] 
} 

Bu

nasıl kendi API toplu denetleyici içinde gelen istekleri her yönlendirebilirsiniz/API/schoolm/toplu gönderilir?

+0

1 isteği olan motivasyonu birden isteği ayrılabilir ne? – AJS

+0

Bu bir istek değil - farklı API'lar için kullanılan farklı türlerdir. Bir isteğiyle kulüplere girmek, kodun müşteri tarafımdan yapmak istediğim aramaların sayısını azaltmaktır. – swateek

+0

Yaklaşımınızın doğru olmayabileceğine inanıyorum, eğer düğüm beklediğiniz taleplerin üstesinden gelemezse endişeleniyor musunuz ?, tek bir düğüm noktası, çoğu yükü işleme yeteneğinden daha fazla olduğundan, eğer ölçeklendirilemiyorsa Nodda da çok kolay olan kümeler – AJS

cevap

0

Yapacağını düşünüyorum. Cevabım, clay's yanıtından yoğun bir şekilde ödünç alınmış/ilham almış/alınmıştır. Ve sadece davamda kullandığım tüm detayları ekliyorum. Tekrar teşekkür ederim kil!

İlk burada API yapılandırılmıştır açıklanmıştır:

/api/schoolm çocuk API'leri yönlendirilir ana api

Ve orada taleplerden

geçerli: Toplu opertaions desteklemek için Şimdi

/api/schoolm/students/ 
/api/schoolm/teachers/ 
/api/schoolm/subjects/ 
... 

, ben Tüm parti işlemlerini yürütmekten sorumlu olacak başka bir API ekledi./api/schoolm/batch de

{ 
"batchReq":[ 
    { 
    "id":"1", 
    "uri": "/api/schoolm/students/", 
    "httpMethod": "GET" 
    }, 
    { 
    "id":"2", 
    "uri": "/api/schoolm/teachers/", 
    "httpMethod": "GET" 
    } 
] 
} 

kontrol talebi (iş mantığına) onaylar ve geri referans numarası ile yanıt verir: gibi

/api/schoolm/batch/ 

tipik bir kesikli isteği olmazdı.

var async = require('async'); 
var httpMocks = require('node-mocks-http'); 
var shortid = require('shortid'); 

exports.processBatch = function(batchRequests, callback){ 


    var batchRes = {}; 
    var result = {}; 

    var batchID = shortid.generate(); 
    result.batchID = batchID; 

    async.setImmediate(function() { 
    async.eachSeries(batchRequests, function(batchReq, callback){ 
     var mockRes = httpMocks.createResponse({ 
     eventEmitter: require('events').EventEmitter 
     }); 

     var reqDetails = _processSubRequest(batchReq); 

     _fetchResponse(reqDetails, mockRes); 
     mockRes.on('end',function(){ 
     result[batchReq.id] = mockRes._getData(); 
     callback(null); 
     }); 

    },function(err){ 
     console.log(result); 
    }); 
    }); 

    callback("Your batch request has been accepted. Request ID - "+batchID); 
} 

function _processSubRequest(batchReq){ 
    var retValue = {}; 
    var request = {}; 
    var uriComp = batchReq.uri.split('/'); 
    retValue.controller = uriComp[3]; 

    request.method = batchReq.httpMethod; 
    request.url = batchReq.uri; 
    request.body = batchReq.body || {}; 
    request.params = batchReq.params || {}; 

    if(batchReq.httpMethod == 'GET'){ 
     if(uriComp.length > 5){ 
     request.params.id = uriComp[4]; 
     } 
    }else if(batchReq.httpMethod == 'POST'){ 

    }else{ 

    } 
    retValue.request = request; 
    return retValue; 
} 

function _fetchResponse(reqDetails, mockRes){ 
    var mockReq = httpMocks.createRequest(reqDetails.request); 
    // proceed to fetch answer from respective controller methods. 
    ....................... 
} 

function _prepResponse(result, err, res){ 
    var data = {}; 

    if(err) { 
    data["error"] = err; 
    data["response"] = null; 
    return data; 
    }else{ 
    data["error"] = null; 
    data["response"] = result; 
    return data; 
    } 
} 

toplu işlem tamamlandıktan sonra

, canlı bildirimin parçası olarak kullanıcıya gönderilen veya sonradan gelen okunacak DB saklanabilir. Toplu isteği için GraphQL üzerine

1

Yönlendirme tablolarınızı iki kez tanımlamanız gerektiği gibi görünüyor. Mantığınızı biraz ayırabilirsiniz, böylece fonksiyonlara daha kolay erişebilirsiniz.

app.get('/api/schoolm/students', studentController.getStudents); 
app.post('/api/schoolm/teachers', teachController.postTeachers); 

gibi StudentsController ve TeacherController, bu yüzden tanımlayabilirsiniz Ekspres yolları tanımlayın ancak hala beton yönteminde erişin. DÜZENLEME: Muhtemelen ana mantığı daha fazla parçalamak isteyebilirsiniz, bu nedenle doğrudan toplu iş yöntemlerini çağırabilirsiniz.

StudentController.prototype.getStudents = function(params, callback){ 
    //do stuff 
    callback(null, studentList); 
} 

StudenController.prototype.getStudentsRequest = function(req, res){ 
    this.getStudents({}, function(err, students){ 
    //check error 
    res.send(students); 
    }); 
} 

//elsewhere, in routing table 
app.get('/api/schoolm/students', studentController.getStudentsRequest); 

//elsewhere, in batching method 
//api route that matches students 
studentController.getStudents(batchReq[index].value, function(err, students){ 
    //do something with students, like put in outer results object. 
    //call async.each's callback(), or whatever for control flow 
}); 

Alternatif olarak, doğrudan denetleyicileri çağırmak için sahte req ve res nesneleri yapabiliriz. node-mocks-http gibi bir şey.

Elbette, yığınlama nesnesinde belirtilen yolları yeniden ayrıştırmanız gerekir, böylece doğru denetleyici yöntemini çağırabilir ve sonuçları depolayabilirsiniz. Belki de director gibi bir şey (veya dahili olarak hangi ifade kullanılırsa kullanılsın) yardımcı olur. Express'te

Tipik yolları sonunda tepkilerini gönderecek ve gerçekten hç ya da (iki kere res.end diyemezsin gibi) başka bir yerde bunları kullanamaz böylece res.send yanı res.end diyebiliriz.

Gerçekten de, neden sadece istemciden birden çok istek göndermeyin. O zaman müşteriye de bir parti cevabı ayırmak zorunda değilsiniz. Bu,

+0

Google'ın nasıl işlediğini toplu işleyen API'ların nasıl işlediğini merak ediyorum. Salesforce bile bunu yapıyor. Ancak sahip oldukları tek şey, müşteri isteğinin nasıl gönderilmesi gerektiğidir, kimse arka planda nasıl işlendiğinden bahseder. – swateek

+0

Sonunda, toplu olarak her bir öğe için doğru işlevi çağırmanız gerekir; bu, temel olarak yalnızca regex ayrıştırmadır. Yol parametreleriniz varsa, yönetmen veya [route-parser] (https://www.npmjs.com/package/route-parser) gibi işleri daha kolay hale getirmek istersiniz. Parti'lerin ne kadar sürede işleneceğine (veya parti içinde kaç adet maddenin bulunabileceğine) dikkat edin, böylece orijinal istek beklerken zaman aşımına uğramamaktadır. – clay

+0

İşlemin sona ermesi hakkında kullanıcıyı bilgilendirmek için bu parçaya, uyumsuz işleme ve bir bildirim mekanizmasına dikkat etmelisiniz. – swateek

0

çevirin :)