具有完成阶段的多个ajax请求的进度条。可能吗?

时间:2016-07-03 18:17:24

标签: javascript jquery ajax xmlhttprequest

我有一个简单的表单,当通过ajax请求提交验证时。如果表单检出正常,则进行另一个ajax请求以处理最初提交的数据。

我想为此构建一个进度条。我发现将此代码添加到每个ajax请求会分别返回每个调用的进度。这使得进度条加载到100%,快速加载两次。

例如,每个填充50%进度条的两个ajax请求是否可能?...所以ajax请求1将填充高达50%,第二个将填充51%到100%?还是那么疯狂?

或者,如果三个ajax调用每个负责占总百分比的33.33%?

我想我们更关注完成阶段和进展。

任何想法如何在没有太多假装的情况下实现这一目标?

var xhr = new window.XMLHttpRequest();
//Upload progress
xhr.upload.addEventListener("progress", function (evt) {
    if (evt.lengthComputable) {
        var percentComplete = evt.loaded / evt.total;
        //Do something with upload progress
        console.log('percent uploaded: ' + (percentComplete * 100));
    }
}, false);
//Download progress
xhr.addEventListener("progress", function (evt) {
    if (evt.lengthComputable) {
        var percentComplete = evt.loaded / evt.total;
        //Do something with download progress
        console.log('percent downloaded: ' + (percentComplete * 100));
    }
}, false);
return xhr;

2 个答案:

答案 0 :(得分:1)

我创建这样一个进度条的方式是,因为你希望一个接一个地调用你的每个函数,即完成一个应该触发另一个,XMLHttpRequest有onreadystate change事件。您可以使用该事件确认第一个请求是否成功执行,然后触发第二个请求,在每次更改时,您将按进度条增加任意%。

function postdata()
{
    var xhr = new XMLHttpRequest();
    xhr.open
        (
            "POST",
            Url,
            true
        );
    xhr.send();
    xhr.onreadystatechange = function()
    {
        if (xhr.readyState == 4)
        {
            //Call next function here and increment progressbar
        }
    }
}

希望这会有所帮助

答案 1 :(得分:0)

是的,有可能。您可以创建包含每个ajax调用的数组。将<progress>元素max属性设置为100/array.length。按类别evt.loaded / evt.total划分个别progress事件的.length以设置value元素的<progress>。您还可以使用Promise.all().then()来处理从ajax调用返回Promise并更新<progress>元素的函数数组。

HTML

<label></label>
<progress value="0" min="0" max="100"></progress>

的javascript

var progress = document.querySelector("progress");
var url = "/echo/html/";

function request(url) {
var len = arr.length;
return new Promise(function(resolve, reject) {
  var xhr = new XMLHttpRequest();
  xhr.upload.addEventListener("progress", function(evt) {
    if (evt.lengthComputable) {   
      var percentComplete = ((evt.loaded / evt.total) * (progress.max / len)) 
                            / len;
      progress.value += percentComplete;
      console.log(progress.value, percentComplete);
      if (evt.total === evt.loaded) {
        requests += 1;
      }
      if (progress.value == progress.max && requests === len) {
        progress.previousElementSibling.innerHTML = "upload complete";
        // you could call `resolve()` here if only interested in
        // `upload` portion of request
        alert("upload complete");
      }
    }
  }, false);
  xhr.onload = function() {
     resolve(this.responseText)
  };
  xhr.onerror = reject;
  xhr.open("POST", url, true)
  xhr.send("html=" + Array(100000).fill(1).join(""));
  })
}

var arr = [], requests = 0;
arr.push(request, request, request);
Promise.all(arr.map(function(req) {
  return req(url)
}))
.then(function(data) {
  console.log(data);    
})
.catch(function(err) {
  console.log(err)
})

jsfiddle https://jsfiddle.net/v2msL7hj/3/