用promise.race实现等待过程中加载动画

247 阅读1分钟

在请求过程中,有时候因为网速过慢导致等待时间过长。为了优化体验,在加载过程中显示一个动画,在网速快时不显示动画,则可以考虑用promise.race方法。

Promise.race(iterable) 方法接收一个可迭代对象作为参数,返回一个 promise。迭代器中的某个promise解决或拒绝,返回的 promise 就会解决或拒绝,也就是说谁先有响应就返回谁的结果。

        const promise1 = new Promise((resolve, reject) => {
            setTimeout(resolve, 500, 'promise 1 resolved');
        });

        const promise2 = new Promise((resolve, reject) => {
            setTimeout(reject, 100, 'promise 2 rejected');
        });

        const promise3 = new Promise((resolve, reject) => {
            setTimeout(resolve, 200, 'promise 3 resolved')
        });

        (async () => {
            try {
                let result = await Promise.race([promise1, promise2, promise3]);
                console.log(result);
            } catch (err) {
                console.error(err);
            }
        })();
         // 输出:promise 2 rejected
        // 因为promise2最先有响应,所以返回的是cacth到的reject值

因此,可以编写一个timeout函数,来判断是接口先有响应还是timeout函数先有响应,如果timeout先有就说明需要显示loading,否则就不需要显示

        // 模拟网络请求
        function getUserInfo(user) {
            return new Promise((resolve, reject) => {
                setTimeout(() => resolve("user data!"), Math.floor(900 * Math.random()));
            });
        }

        // 模拟接口请求
        function showUserInfo(user) {
            return getUserInfo().then(info => {
                // 这里处理业务逻辑
                console.log(info)

                // return值用来告诉promise.rece()请求完成
                return true;
            });
        }

        // loading函数
        function showSpinner() {
            console.log("please wait...")
        }

        // 延迟函数
        function timeout(delay, result) {
            return new Promise(resolve => {
                setTimeout(() => resolve(result), delay);
            });
        }

        // 如果300ms后timeout没有响应,就显示loading
        Promise.race([showUserInfo(), timeout(300)]).then(displayed => {
            if (!displayed) showSpinner();
        });