mean.io使用http请求堆叠长angular度运行操作

我正在使用平均值堆栈开发一个Web应用程序,对几个mongo db集合执行几个操作。

系统总体意图是在几个系统之间执行数据同步。 每个系统数据都存储在不同的集合中。 毋庸置疑,这些collections文件具有共同的性质。

nodeJS或者API级别上,我创build了get和post请求,这些请求将asynchronous地遍历主集合,并尝试将该集合上的文档与其他集合中的文档链接起来。 自然这个过程需要几分钟的时间。

可能链接的文档存储在不同的mongodb集合中。 这些将在稍后的另一个节点js API调用中处理。

API设置后,我正在创build一个控制器和angular度的服务,以连接到API,并执行API获取和发布请求。

当我在UI中点击button来执行这个链接操作时,操作开始时不会阻塞浏览器,但最终浏览器会得到一个ERR_EMPTY_RESPONSE,因为操作仍在进行,所以我从来没有真正调用response.end()

我认为可能是一个可能的解决scheme:

  1. 操作开始后立即回复:PROBLEM – >我需要确保此操作完成,以便对所产生的集合进行其他调用。 所以我做了这个操作来完成,让其他人在结果数据集上完成。

为了避免浏览器在后台长时间运行操作完成之前closures连接,我该怎么做?

码:

html – >用户点击开始链接logging的button:

 <div> <md-button aria-label="link all records" ng-click="vm.linkRecords()"> <md-icon class="mdi mdi-plus"></md-icon>Link Records </md-button> </div> 

控制器 :canLink,canGrade都是布尔variables,所以当服务器正在进行一个操作时,其他任何一个都不能执行。 一旦操作完成,它将返回true,并允许所有操作。

 function linkRecords() { $state.go('app.records.link'); }// END linkRecords page $scope.$on('linkRecords', function(event, batchSize){ if ( canLink && canGrade) { showToast("Started linking records"); canLink = 0; canGrade = 0; recordService.linkRecords(batchSize).then(function(finished){ canLink = finished; canGrade = finished; }); }else if ( !canLink ){ showToast('Cannot link records: - Currently undergoing grading records'); }else if ( !canGrade ){ showToast('Cannot link records: - Currently undergoing linking records'); } });//END linkingRecords 

服务

 function linkRecords(batchSize){ return $http.get(urlRoot+'/link/:'+batchSize); }//END linkRecords 

节点js api:

routes.js:

 //link all records app.post('/link/:batchSize', function(req, res){ var batchSize = req.params.batchSize; functions.linkRecords(batchSize, function(callback){ res.end(true); }); });//END linkRecords 

functions.js:

 linkRecords : function(batchSize, callback){ //link all records in all collections a batchsize at a time async.parallel([ function(callback){ ...open cursor for collection1 and loops over the collections to stitch with other collections. }, function(callback){ ...open cursor for collection2 and loops over the collections to stitch with other collections. } ], function done(err, result){ callback(); }); } 

这听起来像你需要一个更强大的后端基础设施来pipe理,并跟踪这些长期运行的任务。 如果您知道这些操作将花费很长时间(可能是几秒到几分钟或更长时间),那么您必须设置某种types的队列服务来运行这些任务,跟踪这些任务并处理错误情况。

API服务器的唯一责任应该是:

  1. 接收用户请求
  2. 在请求中validation数据,如果入侵,返回即时错误
  3. 如果有效,则将新作业插入到用于开始处理的队列中
  4. 然后,API响应会向用户返回“处理消息”,可能会使用一些ID来跟踪单独的API请求中的进程。

可能为此过程实施的一组可能的API:

 POST /api/links - create a new link process GET /api/links - display all currently running link processes GET /api/links/:id - display a single link process DELETE /api/links/:id - delete (or cancel) a running link process, if needed 

您可以使用几种不同的队列技术来pipe理长时间运行的任务。 如果您在AWS环境中,则可以使用SQS队列 。 如果您的stream程涉及多个步骤,您可以查看处理数据(或stream程)pipe道的系统。 Luigi (来自spotify开源)是一个可以用来处理非常简单的stream水线的例子(即一步),直到具有大量步骤和依赖关系的极其复杂的stream水线。

这是一个教程 ,用长时间运行的stream程来解决这个问题,然后讨论一些可能的实现。

我不是MEAN栈的专家(但是),但是我想你devise你的服务的方式是不正确的。 它将返回一个承诺(结果未完成),并在承诺完成之前致电结束。

尝试devise你的服务和route.js调用这样的东西。

服务

 angular.module('rugCoPro').factory('appraisalSearch', ['$resource', 'RugSession', function($resource, RugSession) { return $resource("/:org/api/models/appraisals/:func/:value", { org: "@org", func: "@func", value: "@value" }, { query: { method: 'GET', isArray: true, headers: { 'Content-Type': 'application/json', 'X-Auth-Token': authToken } } }); }]) 

呼叫

  appraisalSearch(RugSession.getAuthToken()).query({ org: org, func: "multi", value: orderNumber[0] }).$promise.then(function(data) { //success }, function(error) { //error }) 

为了pipe理,我会捎带Mikelax回答使用排队系统。 我一直在使用议程来处理我一直在处理的项目中较长的stream程。

我认为值得一提的是(可能是ERR_EMPTY_RESPONSE错误的根源)Express的默认超时时间为2分钟。 因此,如果您的进程需要几分钟时间,则应该修改端点上的超时以处理请求。

您可以通过几种不同的方式修改超时,还有中间件,比如connect-timeout 。 你也可以通过你的env对象或直接在你的server.js文件中设置超时。