V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐关注
Meteor
JSLint - a JavaScript code quality tool
jsFiddle
D3.js
WebStorm
推荐书目
JavaScript 权威指南第 5 版
Closure: The Definitive Guide
liudaqi
V2EX  ›  JavaScript

JS 怎么在页面实现延时提醒?(外部 API 请求慢 2~3 秒返回数据 | 也可能失连:让用户重新加载一下)

  •  
  •   liudaqi · 2021-02-18 23:26:14 +08:00 · 2253 次点击
    这是一个创建于 1407 天前的主题,其中的信息可能已经有所发展或是发生改变。
    页面上有一个外部地图数据统计的 API 请求,通常会有 2~3 秒的延时,数据好了再异步加载显示。

    但是,由于这个 API 比较拥挤,可能会请求拒绝,然后在页面上提示用户:如果要看地图展示的统计数据,可以重新刷新一下(不看地图数据展示,并不影响页面其他部分)。

    现在经常会出现错误提示:让用户重新刷新一下,其实是过 2~3 秒之后数据就可以了。

    怎么让这个提示晚 5 秒钟左右再出现?(超过 5 秒数据还没准备好,大概率这次网络请求是拿不到数据了,不是速度慢的情况。这个时候去提醒用户)
    14 条回复    2021-03-11 18:25:27 +08:00
    ferock
        1
    ferock  
       2021-02-18 23:28:37 +08:00 via iPhone
    setTimeOut
    liudaqi
        2
    liudaqi  
    OP
       2021-02-18 23:38:12 +08:00
    @ferock setTimeOut 不行,只是把错误的提示延时出现了,还是会出现。

    期望的情况是:5 秒内网络数据加载完了,就不提示;没加载好就提示。
    Zhuzhuchenyan
        3
    Zhuzhuchenyan  
       2021-02-18 23:42:41 +08:00
    Rocketer
        4
    Rocketer  
       2021-02-18 23:50:57 +08:00 via iPhone   ❤️ 6
    Promise.race 会返回第一个执行完成的结果,所以你可以用它同时执行一个 5 秒钟延时的 reject 。如果请求成功了就会忽略这个 reject,如果 5 秒还没成功,就会收到这个 reject 。

    示例代码:

    ```Javascript
    const result = await Promise.race([
    fetch('/your-request-api'),
    new Promise((resolve, reject) => {
    setTimeout(() => reject(‘Timeout’), 5000)
    })
    ]);
    ```
    a570295535
        5
    a570295535  
       2021-02-18 23:51:33 +08:00 via Android
    @liudaqi 前台弄一个 3 个点的 gif 动图显示加载中,ajax 请求地图 api 判断是否返回 200,超时时间设置 5 秒,超时就返回刷新提示
    SilencerL
        6
    SilencerL  
       2021-02-19 00:28:37 +08:00
    楼上 Promise.race 正解, 话说这不是前端基础知识了吗..
    learningman
        7
    learningman  
       2021-02-19 00:38:47 +08:00
    你请求的时候设 timeout,然后把显示提示的代码放 catch 里不就好了
    molvqingtai
        8
    molvqingtai  
       2021-02-19 00:41:52 +08:00
    让用户主动刷新体验不好,请求失败了就自动重试,中途一直显示 loading
    xstmjh
        9
    xstmjh  
       2021-02-19 00:42:25 +08:00
    new Promise(function (resolve, reject) {
    asyncFn(param, function (err, result) {
    if (error) {
    return reject(error);
    }
    return resolve(result);
    });

    setTimeout(function () {
    reject('timeout');
    }, 5000);
    }).then(doSomething);
    ljpCN
        10
    ljpCN  
       2021-02-19 01:47:07 +08:00
    建议楼主详细说说这个错误提示是在什么情形下抛出的。看你的描述,并不是在网络请求失败时抛出的,如果是应该就不存在需要添加延时的问题了。
    Reapper
        11
    Reapper  
       2021-02-19 13:33:26 +08:00
    定时器
    Roger006
        12
    Roger006  
       2021-02-19 13:49:55 +08:00   ❤️ 1
    1 发送请求的时候,同时设置 settimeout [记得保存句柄,清除延时时要用到] ,timer
    2 延时要进行的操作就是提示用户刷新的弹窗方法,此处假设方法名为 waringFn
    3 写一个清理延时的方法,比如 clearTimerFn = ()=>{clearTimeout(timer); timer = null;}
    4 请求本身设定 5 秒超时,catch 里边 [此处捕获异常包含超时、网络问题、端口拒绝等] 调用 waringFn 和 cleaerTimerFn ( catch 里边的操作需要一个判断,判断 timer 是否为 null )
    John60676
        13
    John60676  
       2021-02-20 15:31:52 +08:00
    如果是用 vue3 写的话,可以考虑一下用 vue-request https://github.com/AttoJS/vue-request 来处理,里面有个 错误重试 的模块,应该能解决你面临的问题。
    zeni123
        14
    zeni123  
       2021-03-11 18:25:27 +08:00
    楼主是不是想让外部的 API 延迟发出, 假如外部 API 是打包好的那么只能拦截 XMLHttpRequest 和 send 方法 5 秒钟了...

    下面代码只是示例,还不能运行·

    var sendFunc = XMLHttpRequest.prototype.send;
    XMLHttpRequest.prototype.send = function (data) {

    console.log("wait for 5 seconds before sending a request")
    setTimeout(function () {
    console.log("sending data now");
    sendFunc(data);
    }, 5000);
    };
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3463 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 21ms · UTC 04:48 · PVG 12:48 · LAX 20:48 · JFK 23:48
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.