• 从合并请求角度谈性能优化


    从合并请求角度谈性能优化

      性能优化是前端非常重要的一块,可下手的地方有很多,比如图片层次、JS层次、webpack工程层次、CSS层次、CDN层次等等,其中关于请求的优化是整个项目运行中非常重要的一块,所以这次我们来讲一下请求优化的一个小方法。

    来看需求

      最近在一个React项目中有看见一个类似结构的代码,其中reqData、reqListData、reqProData是三个函数,内部分别有三个不同的Promise请求,请求获得数据后,将数据保存至this.state中。

    componentDidMount() {
        this.reqData();
        this.reqListData();
        this.reqProData();
    }
    
    /**
     * 第一个请求
     **/
    reqData() {
        ajax.getData().then(res => {
            // do something with this.setState({})
        })
    }
    
    /**
     * 第二个请求
     **/
    reqListData() {
        ajax.getListData().then(res => {
            // do something with this.setState({})
        })
    }
    
    /**
     * 第三个请求
     **/
    reqProData() {
        ajax.getProData().then(res => {
            // do something with this.setState({})
        })
    }
    

      事实上,这段代码是没有问题的,毕竟在这个需求中,这三个返回的数据都是互不干扰互不联系的,但是在我们开发的过程中,我们需要有想到可能日后在每个地方都会有变动的地方,假如在后续开发中,我们在第二个请求的时候,需要根据第一个请求返回的数据进行判断再插入this.state中呢?这是一个非常有可能性的需求。

      而且值得注意的是,这是一个React项目,使用this.setState的时候,会触发render方法重新渲染你的界面(这里不考虑其他的,如shouldComponentUpdate等情况),那么这样来构建代码,会产生非常多次的无必要的render,严重影响性能。

      那么我们的需求就很清晰了,我们需要将多次的render缩减为一次,并使得请求返回的数据能够互相有业务逻辑来往,所以在这里,我们选择使用Promise.all

    Promise.all

      Promise.all大家应该不陌生,作为ES6中作为Promise的伴生静态方法,他有一个显著功效:将多个Promise对象实例包装,生成并返回一个新的Promise实例。

      使用这个方法,你可以将多个的Promise以数组参数的形式传入,当所有Promise实例全部(注意是全部)变为resolve后,该方法才会返回,并可在then方法中获得一个数组形式的结果,你可以使用数组解构的方法轻松获取这些参数

    // 使用方法
    Promise.all([p1, p2, p3]).then(function (results) {
        let [res1, res2, res3] = results;
    });
    

      下面的是博主给大家写的示例,让大家简单的了解一下这个Promise.all的使用方法。

    // 示例
    let promise1 = new Promise(function (resolve, reject) {
        if (true) {
            resolve(1);
        } else {
            reject(false);
        }
    });
    let promise2 = new Promise(function (resolve, reject) {
        if (true) {
            resolve(2);
        } else {
            reject(false);
        }
    });
    let promise3 = new Promise(function (resolve, reject) {
        if (true) {
            resolve(3);
        } else {
            reject(false);
        }
    });
    
    Promise.all([promise1, promise2, promise3]).then(function (results) {
        let [res1, res2, res3] = results;
        console.log(res1);
        console.log(res2);
        console.log(res3);
        if (res2 === 2) {
            console.log(res3 * 3);
        }
        // do something with this.setState({})
    });
    
    解决

      OK那么接下来方向就很明确了,于是我将componentDidMount中的代码修改成了以下的结构。

    
    componentDidMount() {
        // ajax此处的ajax只是自己的封装,实际上ajax.reqData()等参数还是 Promise 格式
        Promise.all([ajax.getData(), ajax.getListData(), ajax.getProData()]).then((results) => {
            const [res1, res2, res3] = results;
            // 将结果作为参数传入,根据内部逻辑返回需要setState的数据
            const { data } = this.reqDataFormat(res1);
            const { list } = this.reqListDataFormat(res2);
            const { pro } = this.reqProDataFormat(res3);
            if (list) {
                // pro = list.res;
                // Do something with side effects
            }
            this.setState({ data, list, pro })
        });
    }
    

      合并请求后根据测试,耗时不增反而略有下降,可读性上升,减少三次rander,性能提高。

  • 相关阅读:
    在庫購買管理(MM)
    指図ステータス
    購買発注変更、照会画面に初期表示される発注伝票はどのように決まっているのか
    金額処理
    翻訳
    mysql 与mongodb的特点与优劣
    PHP经典算法
    Linux下PHP安装redis扩展
    Linux上安装Redis教程
    PHP插入法排序
  • 原文地址:https://www.cnblogs.com/JobsOfferings/p/React_Promise_all.html
Copyright © 2020-2023  润新知