常用方法封装

209 阅读2分钟

懒加载

/** 方法一  高度对比 **/
let imgs = [...document.querySelectorAll('img')]; // 先获取所有的图片
window.addEventListener('scroll', function () {
  lazyLoad(imgs)
})
function lazyLoad(imgs) {
  for (let i = 0; i < imgs.length; i++) {
    let height = imgs[i].offsetTop; // 图片的距顶部的高度
    let wheight = window.innerHeight; // 浏览器可视区的高度
    let sheight = document.documentElement.scrollTop; // 页面被卷去的高度
    if (height - sheight <= wheight) { // 判断图片是否将要出现
      imgs[i].src = imgs[i].dataset.src; // 出现后将自定义地址转为真实地址
    }
  }
}
/** 方法二  可视区API **/
let imgs = [...document.querySelectorAll('img')];
window.addEventListener('scroll', function () {
  imgs.forEach(img => {
    //这里其实和Method1的思想一样,不过就是简洁了一些
    if (img.getBoundingClientRect().top < window.innerHeight) {
      let dataSrc = img.getAttribute(' data-src'); // 获取 data-src真实的地址
      img.setAttribute('src', dataSrc); // 将 真实的地址 替换为 src属性
      console.log(img.src);
    }
/** 方法三   观察-->构造函数 **/
function query(selector) {
  return Array.from(document.querySelectorAll(selector));
}

var observer = new IntersectionObserver(
  function (entries, self) {
    entries.forEach((item) => {
      if (item.isIntersecting) {
        let img = item.target
        let src = img.dataset.src
        if (src) {
          img.src = src
          img.removeAttribute('data-src')
        }
        self.unobserve(item.target) //取消观察
      }
    })
    query('.lazy-loaded').forEach(function (item) {
      observer.observe(item); // observe给每个图片添加观察实例
    });
  })

无限滚动

var intersectionObserver = new IntersectionObserver(
  function (entries) {
    // 如果不可见,就返回
    if (entries[0].intersectionRatio <= 0) return;
    loadItems(10); // 请求加载下一个十条数据
    console.log('Loaded new items');
  });
// 开始观察
intersectionObserver.observe(
  document.querySelector('.scrollerFooter')
);

并发限制延时执行

// 事件循环机制导致setTimeout并不是完全准确
const fn = function (delay) {
  return ['a', 'b', 'c'].map((current, i) => {
    return new Promise(function (resolve, reject) {
      setTimeout(() => {
        console.log(current);
        resolve()
      }, i * delay)
    })
  })
}

Promise.all(fn(3000)).then(() => {
  console.log('end')
})

并发限制数量

function multiRequest(urls = [], maxNum) { // maxNum并发数量
  const len = urls.length; // 请求总数量
  const result = new Array(len).fill(false); // 保存请求结果数组
  let count = 0; // 当前完成的数量
  return new Promise((resolve, reject) => {
    while (count < maxNum) {
      fn();
    }
    function fn() {
      let current = count++; // ++先赋值后加
      if (current >= len) { // 边界条件
        // 请求全部完成将promise置为成功状态, result作为promise值返回
        !result.includes(false) && resolve(result);
        return;
      }
      const url = urls[current];
      console.log(`开始 ${current}`, new Date().toLocaleString());
      fetch(url)
        .then((res) => {
          // 保存请求结果
          result[current] = res;
          console.log(`完成 ${current}`, new Date().toLocaleString());
          if (current < len) { // 请求没有全部完成, 递归
            fn();
          }
        })
        .catch((err) => {
          console.log(`结束 ${current}`, new Date().toLocaleString());
          result[current] = err;
          if (current < len) { // 请求没有全部完成, 递归
            fn();
          }
        });
    }
  });
}
multiRequest(['111', '222', '333', '444', '555', '666', '777'], 3)

无感刷新Token

import axios from 'axios'
import { MessageBox} from 'element-ui'
import api from './api'

let UserModule = {
  setToken: (data) => {
    window.sessionStorage.setItem('token', data.token)
  },
  getToken: () => window.sessionStorage.getItem('token'),
  removeToken: () => {
    window.sessionStorage.removeItem('token')
  }
}
let isRefreshing = false; // 是否正在刷新的标记
let retryRequests = []; // 重试队列,每一项将是一个待执行的函数形式
const request = axios.create({
  baseURL: api.baseUrl,
  timeout: 50000,
  withCredentials: true // 跨域
})
// http request 拦截器 Request
request.interceptors.request.use(
  (config) => {
    if (UserModule.getToken()) {
      config.headers['Authorization'] = UserModule.getToken()
    }
    return config
  },
  (error) => {
    Promise.reject(error)
  }
)
// http response 拦截器 Response
request.interceptors.response.use(
  (response) => {
    const res = response.data
    if (res.code !== 0) { // code == 0: 成功
      if (res.message) {
        alert(res.message);
      }
      return Promise.reject(res)
    } else {
      return response.data
    }
  },
  (error) => {
    if (!error.response) return Promise.reject(error)
    // 1001 重新登陆 1002 token过期
    if (error.response.data.code === 1002) {
      const config = error.config
      if (!isRefreshing) {
        isRefreshing = true
        return getTokenFun()
          .then((res) => {
            UserModule.setToken(res.data.data); // 重新设置token
            config.headers['Authorization'] = UserModule.getToken()
            // 刷新token后清空队列中的请求
            retryRequests.forEach((cb) => cb(UserModule.getToken()));
            retryRequests = []; // 重试完清空这个队列
            config.baseURL = '' // 看具体项目url是否包含baseURL
            return request(config)
          })
          .catch(() => {
            resetLogin()
          })
          .finally(() => {
            isRefreshing = false
          })
      } else {
        // 正在刷新token,返回一个未执行resolve的promise
        return new Promise((resolve) => {
          //函数放进队列,等token刷新后直接执行
          retryRequests.push((token: any) => {
            config.baseURL = ''
            config.headers['Authorization'] = token
            resolve(request(config))
          })
        })
      }
    } else if (error.response.data.code === 1001) {
      resetLogin()
    } else {
      alert( error.response.data.message);
      return Promise.reject(error)
    }
  }
)

// 刷新token的请求方法
function getTokenFun() {
  return axios.post(
      api.baseUrl + 'auth-center/auth/refresh_token',
      {old_token: UserModule.getToken() || ''}
  )
}
function resetLogin(title = '身份验证失败,请重新登录!') {
  if (window.location.href.indexOf('/login') === -1) {
    MessageBox.confirm(title, '退出', {
      confirmButtonText: '重新登录',
      cancelButtonText: '取消',
      type: 'warning'
    }).then(() => {
      UserModule.removeToken()
      location.reload()
    })
  }
}
export {request}