【问题标题】:refresh a page only when all the ajax scripts are executed仅在执行所有 ajax 脚本时刷新页面
【发布时间】:2021-09-15 03:33:05
【问题描述】:

单击按钮.button 时,我试图触发几个动作 我首先需要清理每个包含.classToClean 类的<div> 并启动一些ajax 脚本来更新数据库。为此,我选择 $(.classToClean).each(function(index){}); 结构,然后选择 ajax $.ajax({}) 结构。到目前为止,我的代码如下所示。

$(".button").on("click", function () {
  ///// each loop /////
  $( ".classToClean" ).each(function( index ) {
    $.ajax({
      //... (clean 1)
      success:function(response){
        $.ajax({
          //... (clean 2)
          success:function(response){
          }
        });
      }
    });
  });
  ///// /each loop /////
});

一旦干净,我想将新语句写入数据库,但这次我只需要 ajax。结果我得到了这样的结果:

$(".button").on("click", function () {
      ///// each loop /////
      $( ".classToClean" ).each(function( index ) {
        $.ajax({
          //... (clean 1)
          success:function(response){
            $.ajax({
              //... (clean 2)
              success:function(response){
              }
            });
          }
        });
      });
      ///// /each loop /////
      $.ajax({
        //... (write 1)
        success:function(response){
          $.ajax({
            //... (write 2)
            success:function(response){
            }
          });
        }
      });
    });

一切正常,但我想在 each()ajax 完成后刷新。通常我只有一个脚本,所以我添加了一个这样的成功函数

success:function(response){
  location.href = "...";
},

但是因为我有很多脚本要运行,所以似乎没有好地方放它。例如,如果我将它放在"write 2" 成功函数中,有时似乎.each() 还没有完成,因此在执行某些脚本之前会刷新页面。 因此我的问题是:有没有办法只在.eachajax 中执行所有脚本时才刷新?

【问题讨论】:

    标签: javascript jquery ajax function each


    【解决方案1】:

    将这些元素映射到请求承诺数组,以便您可以将数组传递给 Promise.all();

    请注意,success 不是承诺链的一部分,因此您需要 then()

    在每个外部 $.ajax.then() 中返回 #2 ajax 承诺也继续构建承诺链

    类似:

    const cleanRequests = $('.classToClean').map(function (index, element) {
        // return clean 1 to array
        return  $.ajax({ /*clean 1 options*/}).then(function (clean1_response) {
          // return clean2 promise
          return $.ajax({ /*clean 2 options*/ }).then(function (clean2Response) {
            // not sure what you want returned
          });
        });
      }).get();
    
    Promise.all(cleanRequests).then(function (allCleanResults) {
        // all the clean requests are done, do the write stuff
        return $.ajax({/*write 1 options*/}).then(function (write1_response) {
          return $.ajax({ /*write 2 options*/ }).then(function (write2Response) {
            // not sure what you want returned
          });
        });
      })
      .then(function () {
        /// all done, reload page
      })
      .catch(function (err) {
        console.log('Oooops something went wrong');
      });
    

    【讨论】:

    • 我不返回任何值,只是与数据库交互。我正在尝试了解 Promise.all 和 map() 文档..
    • Promise.all() 在传递给它的数组中的所有承诺都已解决后解决。 map() 用于从可迭代集合中返回一个数组
    【解决方案2】:

    尝试使用完成而不是成功

    complete:function(response){
    
    }
    

    实际上,如果您只需要用更新的数据库替换 div,则不需要刷新和清理。只需使用 replaceWith() 替换您的 div 或整个页面或 html() 以防您只想替换几个元素而不是整个页面

    示例:

    $(".button").on("click", function () {
      $.ajax{
      ....
      complete:function(response){
       updatedDiv = "your div html code";
       $(#yourdiv).replaceWith(updatedDiv);
       }
      });
    }
    

    【讨论】:

      【解决方案3】:

      实际上很少有方法。肮脏的方式。初始化一个计数变量并保持检查,如果它变为0,则刷新。

      var c = 0;
      var f = None;
      $(".button").on("click", function () {
            f = 1;
            ///// each loop /////
            c +=1;
            $( ".classToClean" ).each(function( index ) {
              $.ajax({
                //... (clean 1)
                success:function(response){
                  $.ajax({
                    //... (clean 2)
                    success:function(response){
                       c -=1;
                    }
                  });
                }
              });
            });
            ///// /each loop /////
            c +=1 ;
            $.ajax({
              //... (write 1)
              success:function(response){
                $.ajax({
                  //... (write 2)
                  success:function(response){
                     c -= 1;
                  }
                });
              }
            });
          });
          while (true) {
             if (c == 0 && f != None) {
                break;
                //refresh here
             }
         }  
      });
      

      添加了一个更脏的方法来避免这种 while 循环首先运行并提前刷新。我希望问题海报更喜欢使用@charlietfl 的答案或使用如下所示的下划线方法

      Goodway:使用下划线 after https://underscorejs.org/#after

      【讨论】:

      • while 将在发出请求之前运行
      • 在您的肮脏示例中,我们同意第一个 c +=1;应该在循环内。我知道它很脏,但至少它是合乎逻辑且易于理解的。我会测试一下。
      • @charlietfl 这是我关心的问题之一。
      • 非常感谢我喜欢这个主意 =) !