Promise初探

作者: 独爱一乐拉面 | 来源:发表于2017-08-31 01:27 被阅读46次

    遭遇“恶魔金字塔”

    项目需要,封装了一个省市区的地址选择器组件。

    可以根据省份id、城市id和区id对组件设置默认值。逻辑是这样的:

    1. 获取省份列表,选中默认省份;
    2. 第一步成功后,根据默认省份id获取城市列表,选中默认城市;
    3. 第二部成功后,根据默认城市id获取区列表,选中默认区。
     getDefaultOptions = () = >{
        let {
            province: provinceId,
            city: cityId
        } = this.props.defaultValue;
            
        //获取省份
        this.props.dispatch({
            type: 'basic/getProvinceList',
            params: {},
            successCallBack: (rs) = >{
                let provinceList = rs.provinces;
    
                //获取城市
                let params = {
                    province_id: +provinceId
                };
                this.props.dispatch({
                    type: 'storage/getCityList',
                    params,
                    successCallBack: (rs2) = >{
                        let cityList = rs2.cities;
                        if (cityList == null) {
                            cityList = [];
                        }
    
                        if ( + cityId == 0) {
                            this._getOptions(provinceList, [], []);
                            return;
                        }
                        //获取区
                        let params = {
                            city_id: +cityId,
                        };
                        this.props.dispatch({
                            type: 'storage/getDistrictList',
                            params,
                            successCallBack:  (rs3) = >{
                                let districtList = rs3.districts;
                                if (districtList == null) {
                                    districtList = [];
                                }
                                this._getOptions(provinceList, cityList, districtList);
                        };
                        });
    
                    }
                });
    
            }
        });
     };
    

    出现3层嵌套的回调,这就是传说中的“恶魔金字塔”。确实是恶魔呀,可读性巨差,自己看着都有点晕,更别说其他人了。

    都说ES6的Promise对象让“恶魔金字塔”闻风丧胆,忍不住来体验一下。

    Promise登场

    MDN上这样定义Promise:
    The Promise object represents the eventual completion (or failure) of an asynchronous operation, and its resulting value.

    废话不多说,来看看使用了Promise后的代码是怎样的:

    sendRequest = (type, params) = >{
        return new Promise((resolve, reject) = >{
            this.props.dispatch({
                type,
                params,
                successCallBack: (rs) = >{
                    resolve(rs);
                }
            });
        });
    };
    
    getDefaultOptions = () = >{
        let {
            province: provinceId,
            city: cityId
        } = this.props.defaultValue;
        let provinceList,
        cityList,
        districtList;
        let _promise = this.sendRequest('basic/getProvinceList', {});
        _promise.then(rs = >{
            provinceList = rs.provinces ? rs.provinces: [];
            return this.sendRequest('storage/getCityList', {
                province_id: +provinceId
            })
        }).then(rs = >{
            cityList = rs.cities ? rs.cities: [];
            //只有省份的情况
            if ( + cityId == 0) {
                this._getOptions(provinceList, cityList, []);
                return Promise.reject({
                    notRealPromiseException: true,
                });
            }
            return this.sendRequest('storage/getDistrictList', {
                city_id: +cityId
            });
        }).then(rs = >{
            districtList = rs.districts ? rs.districts: [];
            return this._getOptions(provinceList, cityList, districtList);
        }).
        catch(ex = >{
            if (ex.notRealPromiseException) {
                return true;
            }
            return false;
        });
    };
    

    需要有序地执行异步操作的场景,Promise再适合不过了。相比回调嵌套,层次更分明,可读性强。

    Promise基本原理学习

    无论是在异步操作的执行之前或执行之后,用Promise对象的then方法注册回调,回调都能一致执行。

    很好奇它是怎么做到的,于是自己尝试写了个简易的Promise, 模拟Promise对异步操作的值的代理:
    https://gist.github.com/anonymous/402271e9e9c59958279d0fe096e0a277

    相关文章

      网友评论

        本文标题:Promise初探

        本文链接:https://www.haomeiwen.com/subject/pxyfjxtx.html