链式jQuery ajax调用错误的顺序触发

时间:2017-09-23 16:10:29

标签: javascript jquery ajax promise chained

我有一个选择列表。每个选项都是一组短文。选择特定包时,文本显示在两个表中。每行都有一个"删除"图标,以便可以从捆绑中删除文本。我希望删除后刷新表和选择列表。有三个链式呼叫:

  1. 从db>>

  2. 删除文本
  3. 刷新选择列表并在自定义标记中转储一些数据>>

  4. 从自定义标记获取数据并重建表格

  5. 但他们似乎按照顺序3>>开火1>>我试图重现的解决方案是this。我做错了什么?

    感谢您的帮助!

    ~~~~~~~~~~~~~

    更新

    1和2肯定是顺序执行的(见screenshot)。问题在于3(' createSegTableRows')。这是不会调用服务器的那个。

    ~~~~~~~~~~~~~

    这是代码。 (损坏的位是第一个片段中的最后一个块。)

    代码段1:从选择列表中选择一个选项时会触发:

    
    
    // This fires when a bundle is selected.
    function selectBundle() {
    
      createSegTableRows();
      rowIconActions();
    
      // this creates some rows for a couple of tables
      function createSegTableRows() {
    
        // get "value" from the currently selected option
        var bundle_id = $('select#bundleSelector').find(':selected').prop('value');
    
        // get some strigified JSON data stored in a custom tag
        var inTagData = $('select#bundleSelector').find(':selected').attr('data');
        // convert back to a JSON object
        var inTagData_parsed = JSON.parse(inTagData);
    
        // convert some data from inside the JSON object to HTML table rows 
        var st_table_contents = tableRows(inTagData_parsed.st);
        var tt_table_contents = tableRows(inTagData_parsed.tt);
    
        // populate the tables
        $('#st_seg_table').html(st_table_contents);
        $('#tt_seg_table').html(tt_table_contents);
    
        // this converts JSON data into table rows
        function tableRows(rObj) {
    
          // map to array and sort
          var rArray = $.map(rObj, function(el) {
            return el;
          });
          rArray.sort(function(a, b) {
            return a.join_id > b.join_id;
          });
    
          //	create rows	
          var rows = ""
          for (i = 0; i < rArray.length; i++) {
            var segment_id = rArray[i]['segment_id'];
            var join_id = rArray[i]['join_id'];
            var segment_text = rArray[i]['seg_text'];
    
            // each row has some text and Up/Down/Delete buttons
            rows += "<tr><td class='sid tt'>" + segment_id + " <a title='Up' jid='" + join_id + "'>&#9650</a><a title='Down' jid='" + join_id + "'>&#9660</a> <a title='Remove' jid='" + join_id + "'>&#10005</a> </td><td>" + segment_text + "</td></tr>";
          }
    
          return rows;
        }
        console.log("some table rows");
      }
    
      // actions fired by Up/Down/Delete in each row
      function rowIconActions() {
    
        // find selected option in a <select> list
        var bundle_id = $('select#bundleSelector').find(':selected').prop('value');
    
        // attach an action to the Delete buttons in each table row 
        $('td.sid>a[title="Remove"]').click(function() {
    
          var join_id = $(this).attr('jid');
          var role = $(this).parent().prop('className').split(" ")[1];
    
          // THIS IS THE BIT THAT DOESN'T WORK
          if (join_id && bundle_id) {
            $.post(
              // delete record in db
              'ajax/bundle_delete_join.php', {
                bid: bundle_id,
                jid: join_id
                // rebuild <select> list
              }).then(function() {
              return bundleSelector();
              console.log("some stuff");
              // rebuild tables
            }).done(function() {
              createSegTableRows();
              console.log("done");
            });
          }
        });
      }
    }
    &#13;
    &#13;
    &#13;

    摘录2:重新填充选择列表:

    &#13;
    &#13;
    // This repopulates the select list.
    function bundleSelector() {
    
      if ($("#pairButton").text("Unpair")) {
        var pid = $("#pairButton").attr("pairid");
      }
    
      $.post(
        // collect some criteria and retrieve stuff from db
        'ajax/bundle_selector.php', {
          st: $("#txtId_left").html(),
          tt: $("#txtId_right").html(),
          pair: pid,
          filter_st: $('#bundleFilterCheck_st').prop('checked'),
          filter_tt: $('#bundleFilterCheck_tt').prop('checked'),
          filter_pair: $('#bundleFilterCheck_pair').prop('checked')
        },
        function(data) {
    
          if (data) {
    
            // convert results to a JSON object
            var dataObj = JSON.parse(data);
    
            // create a variable for the options
            var options = '';
    
            if (dataObj != "") {
    
              // loop through the JSON object...
              Object.keys(dataObj).forEach(key => {
    
                var bundle_id = key;
                var role = dataObj[key];
    
                options = options + "<option value='" + bundle_id + "' data='" + JSON.stringify(role) + "'>bundle " + key;
    
                // loop some more...
                Object.keys(role).forEach(key => {
    
                  if (role[key] && key != 'comment' && JSON.stringify(role[key]) != '[]') {
    
                    options = options + " | " + key + ":";
    
                    var segment_id = role[key];
    
                    // convert to an array for sorting
                    var joinDataArray = $.map(segment_id, function(el) {
                      return el;
                    });
    
                    // sort the array
                    joinDataArray.sort(function(a, b) {
                      return a.join_id > b.join_id;
                    });
    
                    // loop through the array
                    for (i = 0; i < joinDataArray.length; i++) {
    
                      var sid = joinDataArray[i]['segment_id'];
    
                      options = options + " " + sid;
    
                    }
                  }
                });
                // add a closing tag to each option
                options = options + "</option>";
              });
              // populate parent element
              $('select#bundleSelector').html(options);
              console.log("some select options");
    
            } else {
              // if there are no results...
              $('select#bundleSelector').html("");
              $('table#st_seg_table').html("");
              $('table#tt_seg_table').html("");
              $('textarea#bundle_comment').html("");
            }
          } else {
            // and again
            $('select#bundleSelector').html("");
            $('table#st_seg_table').html("");
            $('table#tt_seg_table').html("");
            $('textarea#bundle_comment').html("");
          }
        }
      );
    }
    &#13;
    &#13;
    &#13;

1 个答案:

答案 0 :(得分:0)

这里的关键在于理解bundleSelector() 异步

在“不工作的位”你正确地return bundleSelector();,但该函数返回undefined。为了在bundleSelector()完成后运行某些内容,它必须返回一个承诺,并且,为createSegTableRows()按预期工作,该承诺必须不仅在其$.post()已返回时履行,而且还必须所有选项建设完成后。

要实现这一点,bundleSelector()的$ .post(...,fn)调用必须修改为return $.post(...).then(fn),否则调用者不会等待选项构建完成后再继续到createSegTableRows();因此您报告的3-1-2执行顺序。