javascript - 进行 while 循环延迟重复,直到其中的 ajax 调用完成

标签 javascript jquery ajax while-loop

在解释我想做什么之前,先看一下我正在编码的 MCV

$("#button").submit(function(event) {
  event.preventDefault();
  var formData = new FormData(this);
  var myString = $('#textarea').val();
  var myRegexp = /src="blob:([^'"]+)"/gm;
  match = myRegexp.exec(myString);

  var inProgress = 0;

  while (match != null) {

    var xhr = new XMLHttpRequest();
    addr = match[1];

    xhr.open('GET', 'blob:' + addr, true);
    xhr.responseType = 'blob';
    xhr.onload = function(e) {
      if (this.status == 200) {
        var myBlob = this.response;
        var data = new FormData();
        data.append('file', myBlob);

        $.ajax({
          url: "uploader.php",
          type: 'POST',
          data: data,
          contentType: false,
          processData: false,
          beforeSend: function() {
            inProgress++;
          },
          success: function(data) {
            myString = myString.replace("blob:" + addr, data);
          },
          error: function() {
            // error
          },
          complete: function() {
            --inProgress;
          }
        });
      } else {
        // error
      }
    };
    xhr.send();
    match = myRegexp.exec(myString);
  }

  if (!inProgress) {
    formData.set('textarea', myString);
    submitForm(formData);
  }
});

所以,我有一个文本区域,它包含未知数量的 BLOB 对象。我首先尝试使用 regexp 查找这些 BLOB 对象,然后使用名为 uploader.php 的 PHP 文件将它们上传到服务器。文件上传后,它会返回上传文件的URL,我想用文本区域中上传文件的URL替换BLOB URL,然后将文本区域的最终内容提交到服务器进行进一步处理。

事实证明,当我运行代码时,只有正则表达式的最后一个实例被其上传的 URL 替换。其他人保持原样。我怀疑这是因为 while 循环不等待 ajax 请求完成。我在尝试提交表单时遇到了类似的问题,我按照此 answer 中的建议解决了该问题。但这次我不知道如何解决这个问题。

任何想法都值得赞赏

更新:我尝试让ajax同步工作,但我的浏览器说它已被弃用并且不起作用。

最佳答案

看来您并不真正需要它是同步的(而且我看不到最好使异步操作看起来同步的情况),而只需要它是顺序的。

可以通过使用回调来使异步操作按顺序进行(回调可以重写为 Promise,也可以重写为 async/await 方法,但我会保持简单):

// myString is made global for simplicity
var myString;
function uploadBlob(myBlob, addr, callback) {
  var data = new FormData();
  data.append('file', myBlob);

  $.ajax({
    url: "uploader.php",
    type: 'POST',
    data: data,
    contentType: false,
    processData: false,
    success: function(data) {
      // file uploaded OK, replace the blob expr by the uploaded file url(data)
      myString = myString.replace("blob:" + addr, data);
      callback();
    },
    error: function() {
      // error, the uploaded most likely failed, we leave myString alone
      // or alternatively replace the blob expr by empty string
      // because maybe we dont want to post blob in the final form submit
      // uncomment if needed
      // myString = myString.replace("blob:" + addr, "");
      callback();
    }
  });
}

function getBlobAndUpload(addr, callback) {
  var xhr = new XMLHttpRequest();
  xhr.open('GET', 'blob:' + addr, true);
  xhr.responseType = 'blob';
  xhr.onload = function(e) {
    if (this.status == 200) {
      var myBlob = this.response;
      uploadBlob(myBlob, addr, callback);
    } else {
      // error, but callback anyway to continue processing
      callback();
    }
  };
  xhr.send();
}

function processAddresses(addresses, callback, current) {
  var index = current || 0;
  // all addresses processed?
  if (index >= addresses.length) {
    // yes no more address, call the callback function
    callback();
  } else {
    var addr = addresses[index];
    // once the get/upload is done the next address will be processed
    getBlobAndUpload(addr, function() {
      processAddresses(addresses, callback, index + 1);
    });
  }
}

$("#button").submit(function(event) {
  event.preventDefault();
  var formData = new FormData(this);
  var addresses = [];
  // initialize both localString and myString to the content of the textArea
  // localString will be used to extract addresses,
  // while myString will be mutated during the upload process
  var localString = myString = $('#textarea').val();
  var myRegexp = /src="blob:([^'"]+)"/gm;
  match = myRegexp.exec(localString);

  // collect all addresses first
  while (match != null) {

    addr = match[1];

    addresses.push(addr);
    match = myRegexp.exec(localString);
  }
  // initiate sequential processing of all addresses, and
  // pass the callback function triggering the form submit
  processAddresses(addresses, function() {
      // all the successfully uploaded blob exprs in my string should
      // be now replaced by the remote file url now (see commented part
      // in upload blob error for a variation of the feature
      formData.set('textarea', myString);
      submitForm(formData);
  });
});

关于javascript - 进行 while 循环延迟重复,直到其中的 ajax 调用完成,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55188160/

相关文章:

javascript - js 用正则表达式分割将保留不匹配的分隔符

javascript - 使用 jQuery.each 包装和追加数组元素

php - 使用 PHP、Ajax 和 MySQL

javascript - Ajax post 调用返回 parsererror

javascript - 从外部 URL 滚动到页面的一部分

javascript - 不使用表格即可记住输入

javascript - 全日历动态数据参数,精细响应

jquery - 在 Chrome : conditional statement fails on jquery/ajax result

JavaScript/Jquery 正则表达式替换

javascript - 从 native Webview 获取网页的动态内容