用xhr、fetch实现下载进度动态展示效果

最终实现效果:

1.json-server插件准备json数据

data.json

{
  "stu": [
    {
      "name": "cdd",
      "age": "18",
      "gender": "1",
      "nation": "china"
    }
  ]
}

2.封装xhr、fetch

//封装xhr
const xhrRequest = (options = {}) => {
  const { url, method = "GET", onProgress, data = null } = options;
  return new Promise((resolve) => {
    //创建xhr对象
    const xhr = new XMLHttpRequest();
    //监听状态改变
    xhr.addEventListener("readystatechange", () => {
      if (xhr.readyState === xhr.DONE) {
        resolve(xhr.responseText);
      }
    });

    //下载监听进度
    xhr.addEventListener("progress", (e) => {
      //进度根据loaded和total的返回值进行动画显示
      // console.log(e.loaded, e.total);
      onProgress &&
        onProgress({
          loaded: e.loaded,
          total: e.total,
        });
    });
    //上传监听进度与下载类似
    xhr.upload.addEventListener("progress", (e) => {});
    //发起http请求
    xhr.open(method, url);
    xhr.send(data);
  });
};
// 封装fetch
const fetchRequest = (options = {}) => {
  const { url, method = "GET", onProgress, data = null } = options;
  return new Promise(async (resolve) => {
    const resp = await fetch(url, {
      method,
      body: data,
    });
    //下两行也可拿到响应文本吧
    // const body = await resp.text();
    // resolve(body);

    //以下代码获取响应文本和loaded、total值
    const total = +resp.headers.get("content-length");

    const decoder = new TextDecoder();
    let body = "";

    const reader = resp.body.getReader();
    let loaded = 0;
    while (1) {
      const { done, value } = await reader.read();
      if (done) {
        break;
      }
      loaded += value.length;
      body += decoder.decode(value);
      console.log(loaded, total);
      console.log(loaded);
      onProgress &&
        onProgress({
          loaded,
          total,
        });
    }
    resolve(body);

    //fetch不支持上传监听进度,目前w3c正在讨论的一种方案:ServiceWorker->BackgroundFetchManager
  });
};

export { xhrRequest, fetchRequest };

3.编写html页面和样式,并做逻辑处理

html

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <link rel="stylesheet" href="./progress.css">
</head>

<body>
    <div class="box">
        <button>请求</button>

        <div class="progress">
           <div class="content">
                <div class="text">0%</div>
                <div class="outer">
                    <div class="inner">

                    </div>
                </div>
           </div>
        </div>
    </div>
  
    <script type="module" src="./index.js"></script>
  
</body>

</html>

less

* {
  margin: 0;
  padding: 0;
}
.box {
  width: 100%;
  background: #c9c9c9;
  display: flex;
  height: 100vh;
  justify-content: center;
  align-items: center;
}
button {
  margin: 50px auto;
  width: 200px;
  height: 50px;
  background: rgb(54, 52, 52);
  color: white;
  font-size: 22px;
  border-radius: 5px;
}
.progress {
  display: none;
  width: 300px;
  height: 300px;
  position: fixed;
  background: rgb(213, 125, 216);
  z-index: 2;
  border-radius: 5px;
  box-shadow: 1px 2px 5px rgba(0, 0, 0, 0.5);
  .content {
    width: 300px;
    height: 300px;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    .text {
      color: #fff;
      font-size: 46px;
    }
    .outer {
      width: 80%;
      height: 10%;
      background: rgb(255, 255, 255);
      border-radius: 10px;
      .inner {
        width: 0%;
        height: 100%;
        background: rgb(34, 165, 17);
        box-sizing: border-box;
        clip: rect(0, 50%, 100%, 0);
        border-radius: 10px;
      }
    }
  }
}

index.js

import { xhrRequest, fetchRequest } from "./requst.js";
const btn = document.querySelector("button");
const onProgress = (val) => {
  console.log(val);
};
btn.addEventListener("click", async () => {
  //   const res = xhrRequest({ url: "http://localhost:3000/stu" });
  const res = await fetchRequest({ url: "http://localhost:3000/stu", onProgress });
  //   console.log(res);

  showProgress();
});

const doms = {
  progress: document.querySelector(".progress"),
  text: document.querySelector(".text"),
  inner: document.querySelector(".inner"),
};
//展示进度条动画
const showProgress = () => {
  doms.progress.style.display = "block";
  doms.inner.style.transition = " all 0.5s";
  controls(100231, 6000);
};
const controls = (total, speed) => {
  let num = 0;
  let rate = 0;

  let timer = setInterval(() => {
    if (num < total) {
      num += speed;
      let rates = Math.ceil((num / total).toFixed(2) * 100);
      rate = rates < 100 ? rates : 100;
    } else {
      clearInterval(timer);
      setTimeout(() => {
        doms.progress.style.display = "none";
      }, 1000);
    }
    doms.text.innerHTML = rate + "%";
    doms.inner.style.width = rate + "%";
  }, 300);
};
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值