美文网首页
小程序开发(四)使用promise处理异步流程

小程序开发(四)使用promise处理异步流程

作者: youthcity | 来源:发表于2018-07-03 00:29 被阅读355次

    背景

    在小程序中,我们会经常使用官方提供的API,但是大多数API是异步执行的。
    例如,微信获取用户地理位置的API:

    wx.getLocation({
      type: 'wgs84',
      success: (res) => {
        var latitude = res.latitude // 经度
        var longitude = res.longitude // 纬度
      }
    })
    

    可以看到,success事件是以异步回调的形式执行的。当获取用户地理位置成功时,才会执行 success 事件。

    大量的异步回调,会形成回调地狱,导致代码难以维护。例如,下面是小程序内登录的一段逻辑:

    wx.login({
      success: (res) => {
        const { code } = res;
    
        wx.getUserInfo({
          success: (res) => {
            const { userInfo } = res;
    
            wx.request({
              method: 'POST',
              url : '服务端的登录接口',
              data: {
                code,
                userInfo,
              },
              success: (res) => {
                if (res.statusCode === 200) {
                  const token = res.data.token;
                  console.log('登录成功');
                }
              },
              fail: (res) => {
                console.log('异常...')
              },
            })
          }
        })
      }
    })
    

    简单的描述一下这段代码的逻辑:

    1. 调用wx.login,获取 code
    2. 调用wx.getUserInfo,获取 userInfo
    3. 调用wx.request,将codeuserInfo发送给服务器,获取登录token

    在这段代码里面,尽管我们省略了大量的异常处理,仍进行了3次嵌套。当遇到复杂的业务时,嵌套的层级会更深,代码将变得异常难维护。

    使用Promise简化代码

    我们使用Promisewx.login包一层,这样我们就可以链式调用。避免回调嵌套。

    const wx_login = () => {
      return new Promise((resolve, reject) => {
        wx.login({
          success: (res) => {
            resolve(res);
          },
          fail: (err) => {
            reject(err);
          }
        })
      });
    };
    
    wx_login().then((res) => {
        const { code } = res;
      })
      .catch((err) => {
        console.log(err);
      });
    

    通用 Promise 化API方法

    由于小程序的异步API都是success和fail的形式,所以,我们可以封装一个通用的Promise化得方法

    // 原文地址:https://segmentfault.com/a/1190000013150196
    // promisify.js
    module.exports = (api) => {
      return (option, ...params) => {
        return new Promise((resolve, reject) => {
          api(Object.assign({}, option, { success: resolve, fail: reject }), ...params);
        });
      }
    };
    
    const promisify = require('./promisify');
    const wx_login = promisify(wx.login);
    
    wx_login().then((res) => {
      const { code } = res;
    });
    

    使用promisify改进登录的代码

    const promisify = require('../../utils/promisify.js');
    const get_userinfo = promisify(wx.getUserInfo);
    const get_code = promisify(wx.login);
    const wx_request = promisify(wx.request);
    const HOST = 'https://api.xx.cn';
    
    const login = () => {
      return Promise.all([get_userinfo(), get_code()])
        .then((results) => {
          const userinfo = results[0].userInfo;
          const code = results[1].code;
    
          return wx_request({
            url: `${HOST}/oauth`,
            method: 'POST',
            data: {
              userinfo,
              code,
            },
          })
        }).then(res => {
          return res.data;
        });
    };
    
    login().then((res) => {
      const { token } = res;
    })
    

    总结

    异步编程的最高境界,就是根本不用关心它是不是异步。

    使用Promise处理异步流程,帮助我们简化了代码逻辑,避免了层层嵌套的回调,让代码更容易维护。

    但是,面条式代码并不优雅,最好是能将async/await引入到小程序中。代码的逻辑会变得更加清晰,更容易维护。期待,高手指点。

    参考资料

    相关文章

      网友评论

          本文标题:小程序开发(四)使用promise处理异步流程

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