没有UI块的函数处理链

我需要在我的JavaScript / jQuery中执行几个函数,但我想避免阻止UI。

AJAX不是一个可行的解决方案,因为应用程序的性质,这些function将很容易达到成千上万。 异步执行此操作将终止浏览器。

因此,我需要某种方式来链接浏览器需要处理的函数,并且只在第一个函数完成后发送下一个函数。

算法是这样的

步骤2至15

HTTP:获取当前步骤的项目数量(范围从几百到几千)

对于每个项目,HTTP:获取结果

如你所见,我有两个GET请求 – “链”我不知何故需要管理…尤其是最里面的循环立即崩溃浏览器,如果它是异步完成的 – 但我仍然希望用户能够操作页面,因此纯(阻塞)同步方式不起作用。

您可以轻松地异步执行此操作,而无需立即触发所有请求。 您需要做的就是管理队列。 为清楚起见,以下是伪代码。 它很容易转换为真正的AJAX请求:

// Basic structure of the request queue. It's a list of objects // that defines ajax requests: var request_queue = [{ url : "some/path", callback : function_to_process_the_data }]; // This function implements the main loop. // It looks recursive but is not because each function // call happens in an event handler: function process_request_queue () { // If we have anything in the queue, do an ajax call. // Otherwise do nothing and let the loop end. if (request_queue.length) { // Get one request from the queue. We can either // shift or pop depending on weather you prefer // depth first or breadth first processing: var req = request_queue.pop(); ajax(req.url,function(result){ req.callback(result); // At the end of the ajax request process // the queue again: process_request_queue(); } } } // Now get the ball rolling: process_request_queue(); 

所以基本上我们将ajax调用本身转换为伪循环。 它基本上是递归传递的经典延续传递方式。

在您的情况下,请求的示例将是:

 request_queue.push({ url : "path/to/OUTER/request", callback : function (result) { // You mentioned that the result of the OUTER request // should trigger another round of INNER requests. // To do this simply add the INNER requests to the queue: request_queue.push({ url : result.inner_url, callback : function_to_handle_inner_request }); } }); 

这非常灵活,因为您不仅可以选择先处理广度还是先处理深度(shift与pop)。 但是你也可以使用splice将东西添加到队列的中间,或者使用unshift vs push将请求放在队列的头部以获得高优先级请求。

您还可以通过为每个循环弹出多个请求来增加同时请求的数量。 确保每个循环只调用一次process_request_queue以避免同时发生请求的指数增长:

 // Handling two simultaneous request channels: function process_request_queue () { if (request_queue.length) { var req = request_queue.pop(); ajax(req.url,function(result){ req.callback(result); // Best to loop on the first request. // The second request below may never fire // if the queue runs out of requests. process_request_queue(); } } if (request_queue.length) { var req = request_queue.pop(); ajax(req.url,function(result){ req.callback(result); // DON'T CALL process_request_queue here // We only want to call it once per "loop" // otherwise the "loop" would grow into a "tree" } } } 

你可以制作那个ASYNC并使用我前面写过的一个小型库 ,它可以让你对函数调用进行排队。