2017-08-14 73 views
0

目前,我有一些jQuery代码看起来有点像这样呼吁。遍历同步Ajax和承诺

由于同步JS已弃用,我想将此代码移至使用承诺。我将如何实现这一目标?我一直无法找到一个足够接近这个情况的例子。

+0

@KevinB Promise.all()被发射一次的所有请求。如果数组足够大,肯定会耗尽导致请求失败的资源。 – cepharum

+0

您可以使用[] .reduce创建一个接一个地调用它们的链。例如:https://stackoverflow.com/questions/21372320/how-to-chain-execution-of-array-of-functions-when-every-function-returns-deferre –

+0

转向承诺意味着转向异步。 – Bergi

回答

0

你不这样做同步AJAX在浏览器(以及从技术上讲,你可以在某些情况下,但它是一个非常糟糕的主意,这样做是因为它在Ajax调用期间锁定了浏览器)。

相反,您重新设计您的循环,以便只在前一个循环完成时执行下一个Ajax调用,这意味着您必须手动循环,否则不能使用for循环。由于你的代码是伪代码(你不显示真正的ajax操作),我将使用jQuery ajax示例,但只要它返回一个承诺或使用回调来代替您拥有的任何ajax函数信号完成后。

一般的想法是,你为你的ajax调用创建一个函数,并使用它的完成回调增加你的索引,然后运行你的循环的下一次迭代。

function runLoop(data) { 
    var i = 0; 

    function next() { 
     if (i < data.length) { 
      return $.ajax(data[i]).then(function(data) { 
       ++i; 
       return next(); 
      }); 
     else { 
      // all done with loop 
     } 
    } 
    return next(); 
} 

// call it like this 
runLoop(someArray).then(function() { 
    // all done here 
}); 

如果你没有数据的数组,但只想要一个循环索引:

function runLoop(limitVar) { 
    var i = 0; 

    function next() { 
     if (i < limitVar) { 
      return $.ajax(something_with_i_in_it).then(function(data) { 
       ++i; 
       return next(); 
      }); 
     else { 
      // all done with loop 
     } 
    } 
    return next(); 
} 

// call it like this 
runLoop(theLimit).then(function() { 
    // all done here 
}); 

如果limitVar不大,有参与决定是否继续没有其他逻辑环路,也可以使用一点点简单的模式,如果你有一个返回一个承诺一个Ajax功能:如果你没有使用返回一个承诺AJAX功能

function runLoop(limitVar) { 
    var p = Promise.resolve(); 
    for (var i = 0; i < limitVar; i++) { 
     p = p.then(function(prevResult) { 
      return someAjax(i); 
     }); 
    } 
    return p; 
} 

// call it like this 
runLoop(theLimit).then(function() { 
    // all done here 
}); 

,那么它只是一个几行代码将你的函数封装起来,然后你可以更容易地使用这些设计模式。

+0

为什么downvote?这个答案有什么问题?如果您提供反馈,说明为什么它被低估,那么人们只能改善他们的答案来解决反对意见。 – jfriend00

0

使用一些单独的函数处理数组。每次你从数组中取下另一个元素,然后处理它,当它完成时再次调用该函数。如果列表中没有更多项目,则整个过程完成。

 
var listOfRequests = ...; 

new Promise(function(resolve, reject) { 
    requestNext(); 

    function requestNext() { 
     if (!listOfRequests.length) { 
      return resolve(); 
     } 

     var next = listOfRequests.shift(); 

     doAjaxStuff(next, reject, requestNext); 
    } 
}) 

doAjaxStuff(request, errCallback, doneCallback) { 
    ... 
} 
-1

这是一个非常简单的模式:

var queue = Promise.resolve(); 
var nop =() => null; 

for(let i=0; i<limitVar; ++i){ 
    queue = queue.then(() => doAjaxStuff(i)); 
    //or if you want to ignore Errors 
    //queue = queue.then(() => doAjaxStuff(i)).catch(nop); 
} 

queue.then(() => console.log("finished")); 

或者,如果你使用一个数组作为输入:

var done = data.reduce(
    (queue, value, index) => queue.then(() => doSomethingWith(value, index)), 
    Promise.resolve() 
); 

done.then(() => console.log("finished"));