我有一个数组,我在其中推送对象,我使用array.unshift(object)
将对象添加到数组的开头。
我正在使用var object = array.pop()
从数组中检索元素,这是从数组末尾删除对象。
现在我的数组很快就被填满了,这个数组中的多个对象每秒都被推送。每当一个新元素被推入数组时,我需要弹出数组并处理它并进一步发送,这需要时间。
这是在每次间隔1秒后调用方法然后从数组中弹出一个元素并处理它的好方法,但是如果从数组处理对象需要1秒以上,那么接下来对进程方法的调用也应该被延迟,简而言之,进程数组方法应该在每个时间间隔之后调用,但是如果先前的调用仍在处理中则应该等待。
实施它的更好方法是什么?
示例代码:
angular.module('myApp')
.service('DataService', ['$rootScope', 'UpdateService', function($rootScope, UpdateService)
{
// To store array of JSON updates
var arrayOfUpdates = [];
// To store callbacks to which we need to send updates after processing
var arrayofCallbacks = [];
// Method is getting called when there are updates from "UpdateService" server
this.onDataUpdated = function (jsonObj)
{
// This will add this object in the array
arrayOfUpdates.unshift(jsonObj);
}
// This method will process data and send it further
function processData()
{
// Get the last element from the array
var jsonObj = arrayOfUpdates.pop();
// Now process this JSON data
var data = doSomeCalculations(jsonObj);
// There can be 10-20 callbacks at a time
for(var index=0;index<arrayofCallbacks.length;index++)
{
var object = arrayofCallbacks[index];
object.onUpdatedData(data);
}
// After this pop next element and process and send to registered callbacks
// I can not call "processData()" again as it can create loop
// Also calling it after interval might call it when it has not completed processing
}
});
答案 0 :(得分:1)
在我看来,你正在实施一个队列。您希望能够推送到队列的后面(unshift
),这可能会很快发生。您还希望处理队列前面的项目(pop
),但处理阶段需要时间。我的猜测是这些进程是异步操作的,所以你最终会在同一时间发生许多处理步骤,并且遇到一些类似于数据的条件。
除非您需要主动检查队列中的内容(处理函数之外),否则我建议一起删除队列,并使用promise chaining代替队列。
要做到这一点,无论何时触发传入数据事件,而不是使用unshift()
,您只需将数据传递到您的承诺链,直到所有先前的处理完成后才会执行。一些伪js:
// the promise chain (initialised to automatically trigger then())
var worker = Promise.resolve();
// handle incoming data
function incomingData(data){
// process this data AFTER all other processing and update the chain
worker = worker.then(last => processData(data));
}
// process data
function processData(data){
// do work on the data and return a promise if work is async
return ...
}
更新:我建议的第一件事就是阅读Promises。但我会在下面做一个更深入的解释:
设置工作人员。通过将变量设置为Promise.resolve()
,您实际上是在创建已经解决(已完成)的承诺。可以把它想象成一个空队列,完成了它需要完成的所有工作。
获取新的传入数据时更新承诺链。如果你把一个函数放在里面,就像myPromise.then(myFunc)
一样,myFunc一直运行直到myPromise
被解决,这取决于程序员。它可能会在一些api调用返回后或其他一些工作后解决。您可以按如下方式考虑对worker的更新:
想象一下,每次新数据到达时都会运行processData(data)
,并传入收到的data
。现在想象一下,在前一个函数完成之前无法运行该函数。这就是上面代码中发生的事情。所以是的,存储了传入的数据。
答案 1 :(得分:0)
假设你的任务时间是异步的,你可能会想出一个带有promises的递归异步流控制,如下所示;
我们每隔250毫秒将1到10之间的随机数移到arr
数组,同时每1000毫秒弹出一个。定义的限制是10个项目,一旦我们达到limit
值不移位停止。
function doStgAndPop(a){
return new Promise((resolve,reject) => { var id = setTimeout(_ => a.length > 0 ? resolve(a.pop()) : reject(id),1000)});
}
function doStgAndUnshift(a){
return new Promise((resolve,reject) => { var id = setTimeout(_ => a.length < limit ? (a.unshift(~~(Math.random()*10+1)),resolve(a))
: reject(id),250)});
}
function runnerPop(a){
doStgAndPop(a).then(v => (console.log("pop out resulted:",v),runnerPop(a)))
.catch(e => (console.log("array is now empty"),clearSetTimeout(e)));
}
function runnerUnshift(a){
doStgAndUnshift(a).then(v => (console.log("new array after unshift",JSON.stringify(v)),runnerUnshift(a)))
.catch(e => (console.log("array limit:",limit,"reached"),clearSetTimeout(e)));
}
var limit = 10,
arr = [];
runnerUnshift(arr);
runnerPop(arr);
&#13;
我使用的是原生的ES6承诺。 doStgAndPop
返回一个promise并运行一个异步函数(setTimeout
),该函数挂起1000毫秒并从arr
弹出一个项目arr.length > 0
或拒绝该操作。{{1} }非常相似,但每隔250毫秒取消一个项目,直到达到限制,一旦达到限制,它就会拒绝。 doStgAndUnshift
和runnerPop
是递归函数,分别调用runnerUnshift
和doStgAndPop
并接收承诺。在doStgAndUnshift
阶段,我们递归调用转轮函数,并在then
阶段完成操作。