首页 web前端 js教程 Promise实践 实现微信小程序接口封装

Promise实践 实现微信小程序接口封装

Jun 15, 2020 am 10:55 AM
promise

相信很多开发者都遇到过回调地狱的问题。由于微信小程序的API基本都是基于回调函数的异步操作,如果不使用其他框架或者封装API,特别是使用较多的wx.request(),基本很快就会遇到回调地狱的问题,维护起来十分痛苦。

举个例子

假设此时在正在开发一个社交小程序,其中有一个功能的是,小程序用户在登录后,可以查看附近的人。

假设使用以下的实现思路,我们通过wx.getLocation()获取用户当前位置,然后通过wx.request()请求后端数据。但在此之前需要登录,参考之前官方文档推荐的登录方式,先调用wx.login()获取code,再用wx.request()请求开发者服务器,成功返回自定义登录态(一般为access_token或其他令牌形式),之后再用自定义登录态请求业务数据。

为了方便看,我把官方文档里的登录流程贴出来⬇️

28750a8cc0cf3bb67705f8fb097fa62.png

思路确定后,开始尝试coding(以下代码不建议看完)

/* 以下为Page对象的方法 */

getNearby: function() {
  // 判断是否已认证,可采用wx.checkSession()方案
  if (isAuth) {
  // TODO: 获取业务数据
    return
  }
  
  // wx.login获取code
  wx.login({
    success(res) {
      if (res.code) {
      
      // 获取自定义登录态
      wx.request({
        url,
        method, 
        headers,
        data,
        success(res) {
          // 请求成功
          if (res.statuCode === 200) {
            // 读取响应体中的自定义登录态
            let token = res.data.token
            // 保存自定义登录态
            wx.setStorageSync("assess_token", token)
            
            // 获取位置信息
            wx.getLocation({
              success(res) {
                let { latitude, longitude } = res
                
                // 请求业务数据
                wx.request({
                  url, 
                  method, 
                  header,
                  data: { latitude, longitude },
                  success(res) {
                    // 请求成功
                    if (res.statuCode === 200) {
                      let data = res.data
                      // 数据渲染到V层
                      this.setData({ list: data })
                    }
                    // 请求失败
                    else if (res.statuCode === 400) {
                      // TODO
                    }
                    // 其他错误情况状态码处理
                    // TODO
                  }, 
                  fail(err) {
                    // 调用失败处理
                  }
                })
                
              },
              fail(err) {
                // 调用失败处理
              }
            })
          }
          // 请求失败
          else if (res.statuCode == 400) {
            // TODO
          }
          // 其他错误情况的状态码处理
          },
          fail(err) {
            // 调用失败处理
          }
        })
      } 
      else {
        // TODO
        // 登录失败
      }
    }, 
    fail(err) {
      // wx.login()调用失败处理
      // TODO: ...
    }
  }) 
}
登录后复制

回调地狱出现了。气功波代码,别说别人,就连自己看都会觉得恶心。

某天英明的产品经理站了出来,说我们可以加点XXXXX,你可能还得找个地方嵌套其他微信接口或者多加几个if else分支,到时候就找个地方哭吧。

解决方案

从某种意义上来说,当今风暴式的前端生态,仰仗于Node以及ES6+的出现。

ES6后对于异步有多种解决方案。一种是采用generator/yield,但generator函数使用起来其实比较麻烦。另外一种是采用Promise,相对比较简单。ES7也可以采用async/await,但本质上async/await也是基于Promise。下面介绍Promise

Promise


Promise创建

创建Promise很简单,Promise本身是一个构造函数。通过new创建。构造函数的参数为一个回调函数,回调函数有两个参数为resolve和reject(无需手动维护)。resolve和reject是用来改变状态。关于状态放到后边讲。

// Promise实例的创建
let p = new Promise((resolve, reject) => {
  // TODO
})
登录后复制

Promise有个缺点,一旦创建便会立刻执行。所以一般会用一个函数进行包装。

let getPromise = () => {
  return new Promise((resolve, reject) => {
    // TODO    
  })
}
登录后复制

Promise状态

Promise实例有三种状态,pendingresolvedrejectedPromise实例创建后就会处于pending状态。回调函数中的resolvereject就是用来改变Promise实例状态的。当调用resolve时,Promise实例会从pending变成resolved状态,表示成功。当调用reject时,Promise实例会从pending变成rejected状态,表示失败。

let getPromise = () => {
  return new Promise((resolve, reject) => {
    // TODO  
    // 处理结果
    if (result) {
      resolve(successObject)
    } 
    else {
      reject(error)
    }
  })
}
登录后复制

常用方法

最常用的方法为then()和catch()这两个方法,通过then()的传递效用就可以解决回调地狱的问题。

其中then()可接收两个参数,都是回调函数,第一个回调函数用来处理resolved状态,参数为Promise实例调用resolve传递的成功对象。第二回调函数用来处理rejected状态,参数为调用Promise实例调用reject传递的错误对象。

实际中then()我们一般只用来处理resolved的情况,即只传递第一个回调函数。对于rejected情况更多是采用catch()统一处理。

let getPromise = () => {
  return new Promise((resolve, reject) => {
    // TODO  
    // 处理结果
    if (result) {
      resolve(successObject)
    } 
    else {
      reject(error)
    }
  })
}

getPromise()
  .then(res => {
    console.log(res)
    // TODO
  })
  .catch(err => {
    //TODO
  })
登录后复制

使用then()方法可以继续返回一个Promise对象,通过return一个新的Promise,可以持续的向下传递。

getPromise()
  .then(res => {	//第一层Promise
    console.log(res)
    // TODO
    return getPromise()
    )
  .then(res => {	// 第二层Promise
    console.log(res)
    // TODO
  })
  .catch(err => {
    // TODO
  })
登录后复制

其他常用方法有诸如Promise.all()Promise.race()。当需要等待多个Promise结果时会采用。两个方法都是接收一个由Promise组成的对象数组。使用Promise.all()时,只有当全部的Promise对象全部resolved Promise.all()状态才是resolved。而Promise.race()只需有一个Promise对象为resolved时,其状态就为resolved。

更多方法可阅读相关文档。

封装小程序接口


学习了Promise基础,通过封装异步操作,使用Promise链就可以解决回调地狱问题。

因为wx.request()使用频率比较高,先对wx.request()封装。

/* 可以将公用的方法挂在app.js中 */

request: function(method, url, header, data) {
  return new Promise((resolve, reject) => {
    wx.request({
      method, 
      url, 
      header, 
      data,
      success(res) {
        resolve(res)
      },
      fail(err) {
        reject(err)
      }
    })
  })
}
登录后复制

基本框架就这样,我们可以进一步修改,比如请求url的基础路径,添加一些公用的header,针对状态码做一些全局处理等。

request: function(method, url, header = {}, data = {}) {
  // 启动时可将storage中的令牌挂到app.js 
  let token = app.assess_token
  if (token) {
    header["Authorization"] = token
  }
  return new Promise((resolve, reject) => {
    wx.request({
      method, 
      url: "https://api.domain.com/v1" + url,
      header, 
      data,
      success(res) {
        // 请求成功
        if (res.statusCode === 200) {
          resolve(res)
        }
        // 请求成功无响应体
        else if (res.statusCode === 204) {
          /* 
          可做一些成功提示,
          如调用wx.showToast()、wx.showModal()或自定义弹出层等 
          */
          resolve(res)
        }
        // 未认证
        else if (res.statusCode === 401) {
          /* 可做一些错误提示,或者直接跳转至登录页面等 */
          reject(res)
        }
        else if (res.statusCode == 400) {
        /* 可做一些错误提示*/
          reject(res)
        }
        else if (res.statuCode === 403) {
          /* 无权限错误提示*/
          reject(res)
        }
        // ...其他状态码处理
      },
      fail(err) {
        /* 可做一些全局错误提示,如网络错误等 */
        reject(err)
      }
    })
  })
}
登录后复制

封装之后,举个例子,发送请求就可以修改为

/* 方法体中 */
let app = getApp()

app.request("POST", "/auth", {}, { username, password })	 
  .then(res => {  // 第一层请求
    // TODO 成功处理
    return app.request("GET", "/goods", {}, {})
  })
  .then(res => {	// 第二层请求
    // TODO 成功处理
    // 渲染视图
  })
  .catch(err => {
    // TODO 错误处理
  })
登录后复制

封装一下其他的微信接口

/* 可以将公用的方法挂在app.js中 */
wxLogin: function() {
  return new Promise((resovle, reject) => {
    wx.login({
      success(res) {
        if (res.code) {
          resovle(res)
        }
        else {
          reject({ message: "登录失败" })
        }
      },
      fail(err) {
        reject(err)
      }
    })
  })
}

getLocation: function() {
  return new Promise((resolve, reject) => {
    wx.getLocation({
      success(res) {
        resolve(res)
      },
      fail(err) {
        reject(err)
      }
    })
  })
}
登录后复制

对于最初的例子,可以就修改为

/* Page对象的方法 */

getNearby: function() { 
  // 判断是否已认证,可采用wx.checkSession()方案
  if (isAuth) {
    // TODO: 获取业务数据
    return
  }
  
  app.wxLogin()
    .then(res => {
      // 将code发送给开发者服务器,获取自定义登录态
      return app.request("POST", "/auth", {}, { code, res.code })
    })
    .then(res => {
      // 保存自定义登录态
      setStorage("access_token", res.data.access_token)
      // TODO: 其他登录成功操作...	
      return app.getLocation()
    })
    .then(({ latitude, longitude }) => {
      let url = "/nearby?latitude=" + latitude + "&longitude=" + longitude
      return app.request("GET", url)
    })
    .then(res => {
      // TODO: 数据处理
      let data = res.data
      // 渲染视图层
      this.setData({ data })
    })
    .catch(err => {
      // TODO 错误处理
    })
    
}
登录后复制

之后若有需添加新的请求或者其他异步操作,直接在Promise链上操作就行了。

推荐教程:《微信小程序

以上是Promise实践 实现微信小程序接口封装的详细内容。更多信息请关注PHP中文网其他相关文章!

本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

AI Hentai Generator

AI Hentai Generator

免费生成ai无尽的。

热门文章

R.E.P.O.能量晶体解释及其做什么(黄色晶体)
2 周前 By 尊渡假赌尊渡假赌尊渡假赌
仓库:如何复兴队友
4 周前 By 尊渡假赌尊渡假赌尊渡假赌
Hello Kitty Island冒险:如何获得巨型种子
4 周前 By 尊渡假赌尊渡假赌尊渡假赌

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

在Vue应用中遇到Uncaught (in promise) TypeError怎么办? 在Vue应用中遇到Uncaught (in promise) TypeError怎么办? Jun 25, 2023 pm 06:39 PM

Vue是一款流行的前端框架,在开发应用时经常会遇到各种各样的错误和问题。其中,Uncaught(inpromise)TypeError是常见的一种错误类型。在本篇文章中,我们将探讨它的产生原因和解决方法。什么是Uncaught(inpromise)TypeError?Uncaught(inpromise)TypeError错误通常出现在

言出必行:兑现承诺的好处和坏处 言出必行:兑现承诺的好处和坏处 Feb 18, 2024 pm 08:06 PM

在日常生活中,我们常常会遇到承诺与兑现之间的问题。无论是在个人关系中,还是在商业交易中,承诺的兑现都是建立信任的关键。然而,承诺的利与弊也常常会引起争议。本文将探讨承诺的利与弊,并给出一些建议,如何做到言出必行。承诺的利是显而易见的。首先,承诺可以建立信任。当一个人信守承诺时,他会让别人相信自己是一个可信赖的人。信任是人与人之间建立起的纽带,它可以让人们更加

深入了解Promise.resolve() 深入了解Promise.resolve() Feb 18, 2024 pm 07:13 PM

Promise.resolve()详解,需要具体代码示例Promise是JavaScript中一种用于处理异步操作的机制。在实际开发中,经常需要处理一些需要按顺序执行的异步任务,而Promise.resolve()方法就是用来返回一个已经Fulfilled状态的Promise对象。Promise.resolve()是Promise类的一个静态方法,它接受一个

实例解析ES6 Promise的原理和使用 实例解析ES6 Promise的原理和使用 Aug 09, 2022 pm 03:49 PM

利用Promise对象,把普通函数改成返回Promise的形式,解决回调地狱的问题。明白Promise的成功失败调用逻辑,可以灵活的进行调整。理解核心知识,先用起来,慢慢整合吸收知识。

PHP 函数返回 Promise 对象有什么优势? PHP 函数返回 Promise 对象有什么优势? Apr 19, 2024 pm 05:03 PM

优势:异步和非阻塞,不阻塞主线程;提高代码可读性和可维护性;内置错误处理机制。

前端开发利器:Promise在解决异步问题中的作用与优势 前端开发利器:Promise在解决异步问题中的作用与优势 Feb 22, 2024 pm 01:15 PM

前端开发利器:Promise在解决异步问题中的作用与优势引言:在前端开发中,我们经常会遇到异步编程的问题。当我们需要同时执行多个异步操作或处理多个异步回调时,代码往往会变得复杂、难以维护。为了解决这样的问题,Promise应运而生。Promise是一种用于处理异步操作的编程模式,它提供了一种将异步操作以同步方式进行处理的能力,使得代码更加简洁和可读。本文将介

promise对象有哪些 promise对象有哪些 Nov 01, 2023 am 10:05 AM

promise对象状态有:1、pending:初始状态,既不是成功,也不是失败状态;2、fulfilled:意味着操作成功完成;3、rejected:意味着操作失败。一个Promise对象一旦完成,就会从pending状态变为fulfilled或rejected状态,且不能再改变。Promise对象在JavaScript中被广泛使用,以处理如AJAX请求、定时操作等异步操作。

一文带你轻松掌握Promise 一文带你轻松掌握Promise Feb 10, 2023 pm 07:49 PM

前端js学习中,让大家最难受的就是异步的问题,解决异步、回调地狱等问题时你必须得学会promise,对于多数前端程序员来说promise简直就是噩梦,本篇文章就是从通俗易懂的角度做为切入点,帮助大家轻松掌握promise

See all articles