Heim  >  Artikel  >  Web-Frontend  >  Versprechen Sie die Implementierung der WeChat-Applet-Schnittstellenkapselung

Versprechen Sie die Implementierung der WeChat-Applet-Schnittstellenkapselung

hzc
hzcnach vorne
2020-06-15 10:55:122541Durchsuche

Ich glaube, viele Entwickler sind auf das Problem der Rückrufhölle gestoßen. Da es sich bei den APIs des WeChat-Miniprogramms grundsätzlich um asynchrone Vorgänge handelt, die auf Rückruffunktionen basieren, werden Sie im Grunde sehr stark auf das Problem der Rückrufhölle stoßen, wenn Sie keine anderen Frameworks oder gekapselten APIs verwenden, insbesondere wenn Sie viel wx.request () verwenden schnell. Wartung Es war sehr schmerzhaft.

Zum Beispiel

Angenommen, Sie entwickeln gerade ein soziales Applet. Eine der Funktionen besteht darin, dass Benutzer des Applets nach der Anmeldung Personen in der Nähe anzeigen können.

Unter der Annahme, dass die folgende Implementierungsidee verwendet wird, ermitteln wir den aktuellen Standort des Benutzers über wx.getLocation() und fordern dann die Backend-Daten über wx.request() an. Zuvor müssen Sie sich jedoch anmelden. Rufen Sie zunächst wx.login() auf, um den Code abzurufen, und fordern Sie dann mit wx.request() den Entwicklerserver an Der benutzerdefinierte Anmeldestatus wurde erfolgreich zurückgegeben (normalerweise access_token oder ein anderes Token-Formular). Anschließend wird der benutzerdefinierte Anmeldestatus zum Anfordern von Geschäftsdaten verwendet.

Um das Lesen zu erleichtern, habe ich den Anmeldevorgang im offiziellen Dokument veröffentlicht ⬇️

Versprechen Sie die Implementierung der WeChat-Applet-Schnittstellenkapselung

Sobald die Idee feststeht, beginnen Sie mit dem Codieren (dies ist nicht der Fall). Es wird empfohlen, den folgenden Code zu lesen) )

/* 以下为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: ...
    }
  }) 
}

Die Rückrufhölle ist entstanden. Qigong-Wellencodes, ganz zu schweigen von anderen, werden Ihnen schon beim bloßen Anblick übel werden.

Eines Tages stand der weise Produktmanager auf und sagte, dass wir einige XXXXX hinzufügen können. Möglicherweise müssen Sie einen Platz zum Verschachteln anderer WeChat-Schnittstellen finden oder ein paar weitere if else Zweige hinzufügen zu weinen.

Lösung

In gewisser Weise beruht das heutige stürmische Front-End-Ökosystem auf der Entstehung von Node und ES6+.

Nach ES6 gibt es viele asynchrone Lösungen. Eine besteht darin, generator/yield zu verwenden, aber die Verwendung der Funktion generator ist tatsächlich umständlicher. Die andere Möglichkeit besteht darin, Promise zu verwenden, was relativ einfach ist. ES7 kann auch async/await, übernehmen, aber im Wesentlichen basiert async/await auch auf Promise. Nachfolgend vorgestellt: Promise.

Versprechen


Versprechen erstellen

Versprechen selbst ist ein Konstruktor. Erstellt über Neu. Der Parameter des Konstruktors ist eine Rückruffunktion, und die Rückruffunktion verfügt über zwei Parameter: auflösen und ablehnen (keine manuelle Wartung erforderlich). Auflösen und Ablehnen werden verwendet, um den Status zu ändern. Ich werde später über den Status sprechen.

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

Promise hat einen Nachteil, es wird sofort ausgeführt, sobald es erstellt wurde. Daher wird es normalerweise mit einer Funktion umschlossen.

let getPromise = () => {
  return new Promise((resolve, reject) => {
    // TODO    
  })
}

Promise-Status

Promise-Instanzen haben drei Zustände: pending, resolved und rejected Nachdem die Promise-Instanz erstellt wurde, befindet sie sich im pending Zustand. resolve und reject in der Callback-Funktion werden verwendet, um den Status der Promise-Instanz zu ändern. Wenn resolve aufgerufen wird, ändert sich die Promise-Instanz vom Status pending in den Status resolved, was den Erfolg anzeigt. Wenn reject aufgerufen wird, ändert sich die Promise-Instanz vom Status pending in den Status rejected, was auf einen Fehler hinweist.

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

Gemeinsame Methoden

Die am häufigsten verwendeten Methoden sind then() und catch(). Die Callback-Hölle kann durch die Übergabe des Dienstprogramms von then() gelöst werden .

Unter diesen kann then() zwei Parameter empfangen, die beide Rückruffunktionen sind. Die erste Rückruffunktion wird verwendet, um den resolved-Status zu verarbeiten, und der Parameter ist das von der übergebene Erfolgsobjekt Promise Instanzaufrufauflösung. Die zweite Rückruffunktion wird verwendet, um den rejected-Status zu verarbeiten, und der Parameter ist das Fehlerobjekt, das von der aufrufenden Promise-Instanz übergeben wird, die reject aufruft.

In der Praxisthen() verwenden wir es im Allgemeinen nur zur Behandlung der gelösten Situation, dh übergeben nur die erste Rückruffunktion. In rejected-Situationen wird catch() häufiger für eine einheitliche Verarbeitung verwendet.

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
  })

Mit der then()-Methode kann weiterhin ein Promise-Objekt zurückgegeben werden, das kontinuierlich durch returnein neues Promise weitergegeben werden kann.

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

Andere häufig verwendete Methoden sind Promise.all(), Promise.race(). Wird verwendet, wenn auf mehrere Promise-Ergebnisse gewartet werden muss. Beide Methoden empfangen ein Array von Objekten bestehend aus Promise. Bei Verwendung von Promise.all() nur, wenn sich alle Promise-Objekte im resolved Promise.all()-Zustand befinden, ist resolved. Wenn Promise.race() nur ein Promise-Objekt als resolved benötigt, wird sein Status aufgelöst.

Mehr Möglichkeiten, verwandte Dokumente zu lesen.

Kapselung der Mini-Programmschnittstelle


Durch die Kapselung asynchroner Operationen und die Verwendung von Promise-Ketten kann das Callback-Höllenproblem gelöst werden.

Da wx.request() häufiger verwendet wird, kapseln wir zuerst 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链上操作就行了。

推荐教程:《微信小程序

Das obige ist der detaillierte Inhalt vonVersprechen Sie die Implementierung der WeChat-Applet-Schnittstellenkapselung. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:juejin.cn. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen