取消ajax请求时页面闪烁,ajax相应时间过快,页面loading闪烁?

背景

现在绝大部分异步请求都有如下类似的套路代码

loading = true;

ajax().finally(() => {

loading = false;

});

复制代码

都 0202 年了,高速的网络会导致 loading 出现闪烁情况

Promise.all 的解决方案

假设我有两个 ajax 请求时间分别是50ms和150ms,我现在希望不管是50ms还是150ms,loading 动画都有一个比较完整的展示时间

这种情况只需要用一个延迟的 Promise.resolve(),通过 Promise.all 方法去拉长响应时间

const delay = ms => new Promise((resolve, _) => setTimeout(resolve, ms));

loading = true;

Promise.all([ajaxPromise, delay(300)])

.then(handleSuccess)

.catch(handleError)

.finally(() => {

loading = false;

});

复制代码

这种解决方案对于响应快的情况有点本末倒置的感觉

Promise.race 的解决方案

现在我希望响应时间超过100ms的情况才展示 loading 动画

这种情况只需要用一个延迟的 Promise.reject(),通过 Promise.race 方法去和 ajax 竞态

const timeout = ms =>

new Promise((_, reject) => setTimeout(() => reject(Symbol.for('timeout')), ms));

Promise.race([ajaxPromise, timeout(100)])

.then(handleSuccess)

.catch(err => {

if (Symbol.for('timeout') === err) {

loading = true;

return ajaxPromise

.then(handleSuccess)

.catch(handleError)

.finally(() => {

loading = false;

});

}

return handleError(err);

});

复制代码

当我的响应时间为101ms的时候,闪烁还是无法避免的

Promise.all 和 Promise.race 的解决方案

现在我希望响应时间小于100ms时不展示 loading 动画,大于100ms时展示300ms的 loading 动画时间

const timeout = ms =>

new Promise((_, reject) => setTimeout(() => reject(Symbol.for('timeout')), ms));

const delay = ms => new Promise((resolve, _) => setTimeout(resolve, ms));

const request = ({ config, target, timeoutTime = 100, delayTime = 300 }) => {

// 返回promise的ajax请求

const promise = axios(config);

const startLoading = target => {

if (!target) {

return;

}

// startLoading

};

const endLoading = () => {

// endLoading

};

const handleSuccess = data => {

// 兼容Promise.all和Promise.race不同的返回值

const response = Array.isArray(data) ? data[0] : data;

// 处理成功的情况

return Promise.resolve(response.data);

};

const handleError = ({ response }) => {

// 处理失败的情况

return Promise.reject(response);

};

return Promise.race([promise, timeout(timeoutTime)])

.then(handleSuccess)

.catch(err => {

if (Symbol.for('timeout') === err) {

startLoading(target);

return Promise.all([promise, delay(delayTime)])

.then(handleSuccess)

.catch(handleError)

.finally(() => {

endLoading();

});

}

return handleError(err);

});

};

复制代码

timeoutTime 和 delayTime 可以根据自己的网站调整

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值