如何使jquery .each循环等待响应?

时间:2015-12-10 19:01:32

标签: jquery callback aws-lambda

当我调用第二个在AWS中调用脚本并正在等待AWS响应的函数时,如何在.each循环中进行迭代等待? 这是我的.each循环:

$('.subscriptionStatus').each(function(i, obj) {
    var sku = $(this).attr('data-sku');
    subscriptionStatus(sku, function(response) {
        var messageDiv = $(this).closest('.subscriptionMessage');

        var innerHtml = '';
        if (response){
            innerHtml = 'Successful';
        }else{
            innerHtml = 'Failed';
        }
        messageDiv.html(innerHtml);
    }//wait until 
}

对于每次迭代,我正在调用一个函数,在我调用AWS Lambda中的脚本时需要等待其响应,然后继续迭代:

function subscriptionStatus( sku, callback ){
    var lambda = new AWS.Lambda();
    lambda.invoke({
        FunctionName: 'MyFunction',
        Payload: JSON.stringify({
            "sku":sku
        })
    }, function(err, data){
        //response from AWS Lambda

        var success = data.Payload;
        if( success == 'true'){
            //NEED TO PASS TRUE BACK TO THE CURRENT ITERATION OF THE EACH LOOP
            callback(true); //correct way?
        }else{
            //NEED TO PASS FALSE BACK TO THE CURRENT ITERATION OF THE EACH LOOP
            callback(false); //correct way?
        }
    });
}

我的问题是迭代没有等待。
我的代码有什么问题?

2 个答案:

答案 0 :(得分:1)

最简单的方法是使用Promises和Deferreds(在jQuery中)

你的代码大致是:

function subscriptionStatus( sku ){
    var $dfd = jQuery.Deferred();
    var lambda = new AWS.Lambda();
    lambda.invoke({
        FunctionName: 'MyFunction',
        Payload: JSON.stringify({
            "sku":sku
        })
    }, function(err, data){
        if( data.Payload == 'true'){
             $dfd.resolve();
        }else{
            $dfd.reject();
        }
    });
    return $dfd.promise();
}
你现在可以做到:

subscriptionStatus(<sku>)
    .done(function() {

    }).fail(function() {

    });

现在看看这个花哨的部分:如何在你的.each循环中实现它?这取决于它是否需要以正确的顺序或者你必须等到它们全部完成。如果你只是等待所有这些都没有按顺序完成:

// no particular order
var deferreds = []; // does nothing yet
$('.bla').each(function(){
    var $this = $(this);
    var $msgDiv = $this.closest('.subscriptionMessage');
    var sku = $this.attr('data-sku');
    var $dfd = subscriptionStatus(sku)
       .done(function() { $msgDiv.html('Successful'); })
       .fail(function() { $msgDiv.html('Failed'); });
    deferreds.push($dfd);
});
jQuery.when.apply(jQuery,deferreds)
    .done(function() { alert('all successful'); })
    .fail(function() { alert('any of the requests was not succesful'); })
    .always(function() { alert('they are all done'); });

答案 1 :(得分:0)

你有没有得到这个工作?我发现您的代码中的另一个问题与Lambda没有任何关系。您传递给subscriptionStatus的回调中this的值不会是.subscriptionStatus元素。所以最有可能messageDiv始终是一个空的jQuery对象。您可以将其注销以进行验证。

要解决此问题,请在this中保存对.each()的引用,如下所示:

$('.subscriptionStatus').each(function(i, obj) {
  var _this = $(this); // save reference
  var sku = _this.attr('data-sku');
  subscriptionStatus(sku, function(response) {
    // now _this has a reference to the actual jQuery object wrapping the .subscriptionStatus element
    var messageDiv = _this.closest('.subscriptionMessage');

    var innerHtml = '';
    if (response){
        innerHtml = 'Successful';
    }else{
        innerHtml = 'Failed';
    }
    messageDiv.html(innerHtml);
  }//wait until 
}

我怀疑这会解决你的问题,除非你真的想要阻止,直到每个响应都回来(这将损害渲染时间)。如果是这样的话,你应该看看Promises。