一个脚本学会 Promise

感觉之前 对 Promise 理解错误(见之前 2016年的文章:http://www.miaoqiyuan.cn/p/promise),今天周末,抽时间看了 Promise 的文档,确实时理解差太多了。

粗略的看了一个文档,简单的了解了 Promise使用。对于 react-native 中的 API 项目,非常适用( 其实fetch就是一个 Promise实例)。

用 Promise 定义好接口,调用时 最好能统一处理错误,规范为 设计好的数据格式。 文档中 没有 catch 后,能否返回 then的方法。测试结果不能,因为 调用 catch 后,已经时resolved了。如果 catch 继续返回一个 新的 Promise,按 定义的 数据格式,返回一个错误的json, 无视错误,继续操作就完美了。尝试写了一个脚本,实现了我的想法。脚本如下:

new Promise(function(resolve, reject) {
    //模拟API请求数据
    setTimeout(resolve, 100, {
        json: () => ({
            status: 'ok',
            msg: 'foo'
        })
    });
}).then((response) => {
    /**
     * resolve,正常顺序执行
     */
    console.log(">Func1: ", response);
    /**
     * 输出:
     * >Func1: {json: ƒ}
     */
    return response.json();
}).then((json) => {
    /**
     * resolve,正常顺序执行
     */
    console.log(">Func1.1: ", json);
    /**
     * 输出:
     * >Func1.1: {status: "ok", msg: "foo"}
     */
    toCatchError1;
    /**
     * 语法错误,调到 catch
     *  下面的不会执行
     */
    console.log(">Func1.2: " + json);
    return json;
}).catch((err) => {
    /**
     * 触发异常
     */
    console.log(">Err1: " + err);
    /**
     * 输出:
     * >Err1: ReferenceError: toCatchError1 is not defined
     */

    /**
     * 把错误信息封装成Promise,可以继续链式操作
     */
    return new Promise(function(resolve, reject) {
        setTimeout(resolve, 100, {
            status: 'error',
            msg: err
        });
    });
}).then((json) => {
    /**
     * 包裹后resolve,正常顺序执行
     */
    console.log(">Func2: ", json);
    /**
     * 输出:
     * >Func2: {status: "error", msg: ReferenceError: toCatchError1 is not defined
    at Promise.then.then...}
     */
    return {
        code: json.status === 'ok' ? 0 : 1,
        data: json
    };
}).then((res) => {
    /**
     * 继续正常顺序执行了
     */
    console.log(">Func2.1: ", res);
    /**
     * 输出:
     * >Func2.1: Func2=>( Err1 =>( ReferenceError: toCatchError1 is not defined) )
     */
    res.hasError = false;
    return res;
}).catch((err) => {
    /**
     * 前面没有异常,不会触发
     */
    console.log(">Err2: ", err);
    /**
     * 假如出现错误,继续把错误信息封装成Promise,可以继续链式操作
     */
    return new Promise(function(resolve, reject) {
        setTimeout(reject, 100, {
            code: 500,
            hasError: true,
            err: err
        });
    });
}).then((res) => {
    /**
     * 可以正常顺序执行了
     */
    console.log('>Func3: ', res);
    /**
     * 输出:
     * >Func3: {
     *    code: 1,
     *    data: {
     *       status: "error",
     *       msg: ReferenceError: toCatchError1 is not defined at Promise.then.then..
     *    },
     *    hasError: false
     *  }
     */
    return new Promise(function(resolve, reject) {
        var err = true;
        if (!err) {
            setTimeout(resolve, 100, res);
        } else {
            setTimeout(reject, 100, 'Func3 =>( 获取失败 )');
        }

    });
}).then((res) => {
    /**
     * reject,这里执行不到
     */
    console.log('>Func4: ', res.code, res.data);
}).catch((err) => {
    /**
     * reject,出啊发
     */
    console.log('>Err4: ' + err);
    /**
     * 输出:
     * >Err4: Func3 =>( 获取失败 )
     */
});

模式实际应用场景:

//API定义文件( apis.js )
const apiFormat = {
    common: (json) => {
        return {
            code: json.status === 'ok' ? 0 : 1,
            msg: json.msg,
            err: json.status === 'ok' ? false : json.msg
        };
    },
    userInfo: (json) => {
        if (json.err) {
            console.log(err);
        }else{
        	json.desc = json.desc || '还没有填写';
        }
        return json;
    }
};
const connectApi = (method, data) => {
    return new Promise((resolve, reject) => {
        if (data.status === true) {
            setTimeout(resolve, 100, {
                json: () => ({
                    status: 'ok',
                    msg: 'foo'
                })
            });
        } else {
            setTimeout(reject, 100, "网络异常");
        }
    }).then((response) => {
        return response.json();
    }).catch((err) => {
        return new Promise((resolve, reject) => {
            setTimeout(resolve, 100, {
                status: 'error',
                msg: err
            });
        });
    }).then(apiFormat.common);
};


//应用场景一 ( page1.js ), 调用:
connectApi('getUserInfo', { status: true, user: 'abc' }).then(apiFormat.userInfo).then((res) => {
    if (res.code === 0) {
        console.log('调用用户信息成功', res, '用户描述:', res.desc);
    } else {
        console.log('调用用户信息失败', res.err);
    }
});

//应用场景二 ( page2.js ), 调用:
connectApi('getUserExtra', { status: false, user: 'abc' }).then((res) => {
    if (res.code === 0) {
        console.log('调用用户资料成功', res);
    } else {
        console.log('调用用户资料失败', res.err);
    }
});

发表评论

电子邮件地址不会被公开。 必填项已用*标注

This site uses Akismet to reduce spam. Learn how your comment data is processed.