【问题标题】:Update element on every Ajax success response更新每个 Ajax 成功响应的元素
【发布时间】:2021-03-26 07:42:57
【问题描述】:

我有一个循环遍历数组并为数组的每个对象调用 php 脚本的函数。 php 脚本正在从 google maps api 获取 Lat/Lng,所以我需要限制 api 调用。该列表可能很长(当前为 300)。我想在脚本运行时更新用户。

在我的成功回调中,我可以通过控制台记录每个响应,但我想为用户更新的元素只会更新一次。

有没有办法在每次成功响应后更新用户?

这是我的功能:

$('#agents-lat-lng').click(function() {
    
    var data = {
      'action': 'getLatLng'
    }

    $.ajax({
      url: ajax_url,
      type: 'post',
      data: data,
      dataType: 'json',
      success: function(response){

        for ( var i = 0, l = response.query.length; i < l; i++ ) {
        
          $.when(updateLatLngDB(response.query[i]))
          .done(function(dataFromResponses){
          
            console.log('1 ', dataFromResponses[0])
          
          }).fail(function(response){
          
            console.error(response);
          
          });
        
        }
        
      },
      error: function (textStatus, errorThrown) {
        
        console.log(textStatus, errorThrown)
      
      }
    })

  })

这是第二个功能:

function updateLatLngDB(query) {

    var deferred = new $.Deferred()
    var dataFromResponses = []
    var count = 0

      var data = {
        'action': 'updateLatLng',
        'agent': query
      }

      $.ajax({
        url: ajax_url,
        type: 'post',
        data: data,
        dataType: 'json',
        cache: false,
        async: false,
        success: function(response){

          count++
          console.log('count ', count)

          $('#process-upload-response').text(count)
          
          dataFromResponses.push(response)

        },
        error: function (textStatus, errorThrown) {
          
          console.log(textStatus, errorThrown)
          deferred.reject(response)
          
          $('#process-upload-response').html(textStatus, errorThrown)

        }
      })

    deferred.resolve(dataFromResponses)
    return deferred.promise()
  
  }

我已经尝试了从 Deferred 到 setTimout 的所有方法,但是当数组中的每个项目都得到处理时,我无法更新 #process-upload-response。只有在所有响应完成后才会更新。

更新:我已经能够通过将其添加到 for 循环来使其工作

(function(i){

            window.setTimeout(function(){
              
              promises.push(updateLatLngDB(response.query[i],response.query.length));

            }, i * 1000);

          }(i));

【问题讨论】:

    标签: javascript jquery ajax asynchronous


    【解决方案1】:

    问题是您没有在调用 updateLatLngDB 函数之间保持状态,并且您使用空数组解析值,因为您没有在异步调用之外调用解析。

    如果我明白这是你想要的:

    
        $.ajax({
          url: ajax_url,
          type: 'post',
          data: data,
          dataType: 'json',
          success: function(response){
    
            
            var promises = [];
            var updateLatLngDB = countRequests(0);
    
            for ( var i = 0, l = response.query.length; i < l; i++ ) {
              // collect promises
              promises.push(updateLatLngDB(response.query[i]));
            
            }
            // when all request are done execute done
            $.when.apply($, promises).done(function() {
                var dataFromResponses = arguments;
    
                console.log('1 ', dataFromResponses[0])
              
            }).fail(function(response){
              
                console.error(response);
              
            });
            
          },
          error: function (textStatus, errorThrown) {
            
            console.log(textStatus, errorThrown)
          
          }
        })
    
    // keep count in closure
    function countRequests(count) {
       return function updateLatLngDB(query) {
          var deferred = new $.Deferred();
          var data = {
            'action': 'updateLatLng',
            'agent': query
          }
          
    
          $.ajax({
            url: ajax_url,
            type: 'post',
            data: data,
            dataType: 'json',
            cache: false,
            async: false,
            success: function(response){
    
              count++
              console.log('count ', count)
    
              $('#process-upload-response').text(count)
              
              dataFromResponses.push(response);
              
              deferred.resolve(response);
    
            },
            error: function (textStatus, errorThrown) {
              
              console.log(textStatus, errorThrown)
              deferred.reject(response)
              
              $('#process-upload-response').html(textStatus, errorThrown)
    
            }
          })
    
        
        return deferred.promise()
      
      };
    }
    

    注意:如果您不希望所有请求并行完成,您将需要创建异步循环,我喜欢这样编写它们(使用 async/await 更简单,因为您可以创建普通的 while 循环):

    var promises = [];
    var i = 0; = response.query.length;
    (function loop() {
       
        if (i < len) {
            var promise = updateLatLngDB(response.query[i++]);
            promises.push(promise);
            promise.then(loop);
        } else {
            $.when.apply($, promises).done(function() {
                var dataFromResponses = arguments;
    
                console.log('1 ', dataFromResponses[0])
              
            }).fail(function(response){
              
                console.error(response);
              
            });
        }
    })();
    

    这样您就可以延迟每个请求(如果这是您想要的)。

    【讨论】:

    • 不幸的是,这不起作用。我仍然只将最终结果打印到页面而不是计数
    • @Jason 你确定你在response.query 数组中有不止一项吗?我可以模拟 ajax 请求并向您展示,如果您展示您的数据的样子,这是可行的。
    • 我找到了让它工作的方法。看我的更新。我在 for 循环中添加了它
    • 你看到标题为 UPDATE 的新部分了吗?
    • 啊看来得先批了
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-24
    相关资源
    最近更新 更多