亚洲国产日韩欧美一区二区三区,精品亚洲国产成人av在线,国产99视频精品免视看7,99国产精品久久久久久久成人热,欧美日韩亚洲国产综合乱

首頁(yè) 微信小程式 小程式開發(fā) 淺析小程式怎麼實(shí)現(xiàn)登入功能

淺析小程式怎麼實(shí)現(xiàn)登入功能

Dec 06, 2021 am 10:11 AM
小程式 登入

小程式怎麼實(shí)現(xiàn)登入功能?這篇文章為大家介紹小程式登入的正確開啟方式,希望對(duì)大家有幫助!

淺析小程式怎麼實(shí)現(xiàn)登入功能

小程式網(wǎng)路元件

#https://developers.weixin.qq.com/miniprogram /dev/api/network/request/wx.request.html

RequestTask說(shuō)明

方法 #說(shuō)明
RequestTask.abort() 中斷請(qǐng)求任務(wù)。
RequestTask.onHeadersReceived(function callback) 監(jiān)聽 HTTP Response Header 事件。會(huì)比請(qǐng)求完成事件更早。
RequestTask.offHeadersReceived(function callback) 取消監(jiān)聽 HTTP Response Header 事件。
RequestTask.onChunkReceived(function callback) 監(jiān)聽 Transfer-Encoding Chunk Received 事件。當(dāng)接收到新的chunk時(shí)觸發(fā)。
RequestTask.offChunkReceived(function callback) 取消監(jiān)聽 Transfer-Encoding Chunk Received 事件。

wx.request(Object object)屬性

這裡隻列比較常用的屬性,全部屬性請(qǐng)查看連結(jié)。

##請(qǐng)求的參數(shù)headerObject#否設(shè)定請(qǐng)求的header,在header 中不能設(shè)定Referer。 #timeoutnumber否逾時(shí)時(shí)間,單位為毫秒#methodstringsuccessfailfunction否總結(jié)一下:所有的小程式介面基本上都有兩個(gè)特徵:
屬性 類型 預(yù)設(shè)值 必填 說(shuō)明
#url string
#是 #開發(fā)者伺服器介面位址
data string/object/ArrayBuffer

content-type 預(yù)設(shè)為application/json

##GET HTTP 請(qǐng)求方法
function
介面呼叫成功的回呼函數(shù)
function
#介面呼叫失敗的回呼函數(shù)
complete
##介面呼叫結(jié)束的回呼函數(shù)(呼叫成功、失敗都會(huì)執(zhí)行)就算是abort掉的請(qǐng)求!

##參數(shù)都是一個(gè)物件。便於記憶的同時(shí)方便擴(kuò)展。

    都有相同的結(jié)果處理方式:都有success、fail、complete三個(gè)回呼屬性。
  • 介面執(zhí)行的各種情況下的errMsg物件介紹。

回呼屬性

errMsg物件{errMsg:"request:ok"...}
success
fail {errMsg:"request:fail "...} 有的系統(tǒng)這個(gè)fail後面有個(gè)空格,所以要用這個(gè)判斷,最好是用正規(guī)表示式。也可以使用indexOf函數(shù),大於-1來(lái)判斷。
abort {errMsg:"request:fail abort"...}
#

範(fàn)例程式碼

  let reqTask = wx.request({
      url: getApp().globalData.api,
      success(res) {
        if (res.errMsg === "request:ok") console.log("res", res);
      },
      fail(err) {
        // if(err.errMsg.indexOf('request:fail')>-1) console.log('err', err);
        if (/^request:fail/i.test(err.errMsg)) console.log("err", err);
      },
      complete(res) {
        console.log("resOrErr", res);
      },
    });
   const reqTaskOnHeadersReceived = (headers) => {
      reqTask.offHeadersReceived(reqTaskOnHeadersReceived);
      console.log("headers", headers);
      // 由于請(qǐng)求還未完全結(jié)束,所以我們沒(méi)辦法獲得請(qǐng)求的狀態(tài)碼,但是我們可以通過(guò)返回的requestBody的長(zhǎng)度來(lái)進(jìn)行判斷。
      // 兩點(diǎn)說(shuō)明:1. 兩個(gè)~~可以把字符串?dāng)?shù)字快速轉(zhuǎn)化為數(shù)字。
      // 2. 為什么取小于19,是由于后臺(tái)返回沒(méi)有權(quán)限的requestBody的時(shí)候Content-length為“18”,正常情況下是大于19的。所以具體多少得看一下具體情況。
      if (~~headers.header["Content-length"] < 19) reqTask.abort();
    };
    reqTask.onHeadersReceived(reqTaskOnHeadersReceived);

小程式登入介面

  • ##wx .getUserProfile(Object object)

    取得使用者資訊。頁(yè)面產(chǎn)生點(diǎn)擊事件(例如

    buttonbindtap 的回調(diào)中)後才可調(diào)用,每次請(qǐng)求都會(huì)彈出授權(quán)窗口,用戶同意後返回 userInfo。此介面用於取代 wx.getUserInfo,詳見 使用者資訊介面調(diào)整說(shuō)明

  • wx.checkSession(Object object)

    檢查登入態(tài)是否過(guò)期。透過(guò) wx.login 介面獲得的使用者登入態(tài)擁有一定的時(shí)效性。使用者越久未使用小程序,使用者登入態(tài)越有可能失效。反之如果使用者一直在使用小程序,則使用者登入態(tài)一直保持有效。具體時(shí)效邏輯由微信維護(hù),對(duì)開發(fā)者透明。開發(fā)者只需要呼叫 wx.checkSession 介面檢測(cè)目前使用者登入態(tài)是否有效。

    登入態(tài)過(guò)期後開發(fā)者可以再呼叫 wx.login 取得新的使用者登入狀態(tài)。呼叫成功說(shuō)明目前 session_key 未過(guò)期,呼叫失敗說(shuō)明 session_key 已過(guò)期。更多使用方法詳見

    小程式登入。

  • wx.login(Object object)

    #呼叫介面取得登入憑證(code)。透過(guò)憑證進(jìn)而換取使用者登入態(tài)訊息,包括使用者在目前小程式的唯一識(shí)別(openid)、微信開放平臺(tái)帳號(hào)下的唯一識(shí)別(unionid,若目前小程式已綁定到微信開放平臺(tái)帳號(hào))及本次登錄的會(huì)話金鑰(session_key)等。使用者資料的加解密通訊需要依賴會(huì)話金鑰完成。更多使用方法詳見

    小程式登入。

後端登入介面程式碼實(shí)作

#後端使用NodeJS,web框架KOA版本^2.13 .4,路由框架@koa/router版本^10.1.1,框架request,版本^2.88.2,jsonwebtoken用來(lái)加密解密token訊息,版本^8.5.1#

// app.js
const Koa = require("koa");
const Router = require("@koa/router");
const WeixinAuth = require("./lib/koa2-weixin-auth");
const jsonwebtoken = require("jsonwebtoken");

const app = new Koa();
// 小程序機(jī)票信息
const miniProgramAppId = "*********";
const miniProgramAppSecret = "***********";
const weixinAuth = new WeixinAuth(miniProgramAppId, miniProgramAppSecret);

const JWT_SECRET = "JWTSECRET";
// 路由中間件需要安裝@koa/router
// 開啟一個(gè)帶群組的路由
const router = new Router({
  prefix: "/user",
});
// 這是正規(guī)的登陸方法
// 添加一個(gè)參數(shù),sessionKeyIsValid,代表sessionKey是否還有效
router.post("/weixin-login", async (ctx) => {
  let { code, userInfo, encryptedData, iv, sessionKeyIsValid } =
    ctx.request.body;
   // 解析openid
  const token = await weixinAuth.getAccessToken(code);
  userInfo.openid = token.data.openid;
  // 這里可以自己進(jìn)行處理,比方說(shuō)記錄到數(shù)據(jù)庫(kù),處理token等
  let authorizationToken = jsonwebtoken.sign(
    { name: userInfo.nickName },
    JWT_SECRET,
    { expiresIn: "1d" }
  );
  Object.assign(userInfo, { authorizationToken });
  ctx.status = 200;
  ctx.body = {
    code: 200,
    msg: "ok",
    data: userInfo,
  };
});
// lib/koa2-weixin-auth.js
const querystring = require("querystring");
const request = require("request");

const AccessToken = function (data) {
  if (!(this instanceof AccessToken)) {
    return new AccessToken(data);
  }
  this.data = data;
};

/*!
 * 檢查AccessToken是否有效,檢查規(guī)則為當(dāng)前時(shí)間和過(guò)期時(shí)間進(jìn)行對(duì)比
 *
 * Examples:
 * ```
 * token.isValid();
 * ```
 */
AccessToken.prototype.isValid = function () {
  return (
    !!this.data.session_key &&
    new Date().getTime() < this.data.create_at + this.data.expires_in * 1000
  );
};

/**
 * 根據(jù)appid和appsecret創(chuàng)建OAuth接口的構(gòu)造函數(shù)
 * 如需跨進(jìn)程跨機(jī)器進(jìn)行操作,access token需要進(jìn)行全局維護(hù)
 * 使用使用token的優(yōu)先級(jí)是:
 *
 * 1. 使用當(dāng)前緩存的token對(duì)象
 * 2. 調(diào)用開發(fā)傳入的獲取token的異步方法,獲得token之后使用(并緩存它)。

 * Examples:
 * ```
 * var OAuth = require(&#39;oauth&#39;);
 * var api = new OAuth(&#39;appid&#39;, &#39;secret&#39;);
 * ```
 * @param {String} appid 在公眾平臺(tái)上申請(qǐng)得到的appid
 * @param {String} appsecret 在公眾平臺(tái)上申請(qǐng)得到的app secret
 */
const Auth = function (appid, appsecret) {
  this.appid = appid;
  this.appsecret = appsecret;
  this.store = {};

  this.getToken = function (openid) {
    return this.store[openid];
  };

  this.saveToken = function (openid, token) {
    this.store[openid] = token;
  };
};

/**
 * 獲取授權(quán)頁(yè)面的URL地址
 * @param {String} redirect 授權(quán)后要跳轉(zhuǎn)的地址
 * @param {String} state 開發(fā)者可提供的數(shù)據(jù)
 * @param {String} scope 作用范圍,值為snsapi_userinfo和snsapi_base,前者用于彈出,后者用于跳轉(zhuǎn)
 */
Auth.prototype.getAuthorizeURL = function (redirect_uri, scope, state) {
  return new Promise((resolve, reject) => {
    const url = "https://open.weixin.qq.com/connect/oauth2/authorize";
    let info = {
      appid: this.appid,
      redirect_uri: redirect_uri,
      scope: scope || "snsapi_base",
      state: state || "",
      response_type: "code",
    };
    resolve(url + "?" + querystring.stringify(info) + "#wechat_redirect");
  });
};

/*!
 * 處理token,更新過(guò)期時(shí)間
 */
Auth.prototype.processToken = function (data) {
  data.create_at = new Date().getTime();
  // 存儲(chǔ)token
  this.saveToken(data.openid, data);
  return AccessToken(data);
};

/**
 * 根據(jù)授權(quán)獲取到的code,換取access token和openid
 * 獲取openid之后,可以調(diào)用`wechat.API`來(lái)獲取更多信息
 * @param {String} code 授權(quán)獲取到的code
 */
Auth.prototype.getAccessToken = function (code) {
  return new Promise((resolve, reject) => {
    const url = "https://api.weixin.qq.com/sns/jscode2session";
    //由于此框架版本很久沒(méi)有更新了,此處地址發(fā)生了變化,需要修改為以上地址,不然會(huì)出現(xiàn)
    //41008錯(cuò)誤。這也是沒(méi)有直接使用框架,引用本地使用的原因。
    // const url = "https://api.weixin.qq.com/sns/oauth2/access_token";
    const info = {
      appid: this.appid,
      secret: this.appsecret,
      js_code: code,
      grant_type: "authorization_code",
    };
    request.post(url, { form: info }, (err, res, body) => {
      if (err) {
        reject(err);
      } else {
        const data = JSON.parse(body);
        resolve(this.processToken(data));
      }
    });
  });
};

/**
 * 根據(jù)refresh token,刷新access token,調(diào)用getAccessToken后才有效
 * @param {String} refreshToken refreshToken
 */
Auth.prototype.refreshAccessToken = function (refreshToken) {
  return new Promise((resolve, reject) => {
    const url = "https://api.weixin.qq.com/sns/oauth2/refresh_token";
    var info = {
      appid: this.appid,
      grant_type: "refresh_token",
      refresh_token: refreshToken,
    };
    request.post(url, { form: info }, (err, res, body) => {
      if (err) {
        reject(err);
      } else {
        const data = JSON.parse(body);
        resolve(this.processToken(data));
      }
    });
  });
};

/**
 * 根據(jù)openid,獲取用戶信息。
 * 當(dāng)access token無(wú)效時(shí),自動(dòng)通過(guò)refresh token獲取新的access token。然后再獲取用戶信息
 * @param {Object|String} options 傳入openid或者參見Options
 */
Auth.prototype.getUser = async function (openid) {
  const data = this.getToken(openid);
  console.log("getUser", data);
  if (!data) {
    var error = new Error(
      "No token for " + options.openid + ", please authorize first."
    );
    error.name = "NoOAuthTokenError";
    throw error;
  }
  const token = AccessToken(data);
  var accessToken;
  if (token.isValid()) {
    accessToken = token.data.session_key;
  } else {
    var newToken = await this.refreshAccessToken(token.data.refresh_token);
    accessToken = newToken.data.session_key;
  }
  console.log("accessToken", accessToken);
  return await this._getUser(openid, accessToken);
};

Auth.prototype._getUser = function (openid, accessToken, lang) {
  return new Promise((resolve, reject) => {
    const url = "https://api.weixin.qq.com/sns/userinfo";
    const info = {
      access_token: accessToken,
      openid: openid,
      lang: lang || "zh_CN",
    };
    request.post(url, { form: info }, (err, res, body) => {
      if (err) {
        reject(err);
      } else {
        resolve(JSON.parse(body));
      }
    });
  });
};

/**
 * 根據(jù)code,獲取用戶信息。
 * @param {String} code 授權(quán)獲取到的code
 */
Auth.prototype.getUserByCode = async function (code) {
  const token = await this.getAccessToken(code);
  return await this.getUser(token.data.openid);
};

module.exports = Auth;

小程式端登入程式碼實(shí)作

<!--pages/index.wxml-->
<view class="page-section">
    <text class="page-section__title">微信登錄</text>
    <view class="btn-area">
        <button  bindtap="getUserProfile" type="primary">登錄</button>
    </view>
</view>
// pages/index.js
Page({
  /**
   * 頁(yè)面的初始數(shù)據(jù)
   */
  data: {},
  // 正確的登錄方式
  getUserProfile() {
    // 推薦使用wx.getUserProfile獲取用戶信息,開發(fā)者每次通過(guò)該接口獲取用戶個(gè)人信息均需用戶確認(rèn)
    // 開發(fā)者妥善保管用戶快速填寫的頭像昵稱,避免重復(fù)彈窗
    wx.getUserProfile({
      desc: "用于完善會(huì)員資料", // 聲明獲取用戶個(gè)人信息后的用途,后續(xù)會(huì)展示在彈窗中,請(qǐng)謹(jǐn)慎填寫
      success: (res) => {
        let { userInfo, encryptedData, iv } = res;
        const requestLoginApi = (code) => {
          // 發(fā)起網(wǎng)絡(luò)請(qǐng)求
          wx.request({
            url: "http://localhost:3000/user/weixin-login",
            method: "POST",
            header: {
              "content-type": "application/json",
            },
            data: {
              code,
              userInfo,
              encryptedData,
              iv,
            },
            success(res) {
              console.log("請(qǐng)求成功", res.data);
              let token = res.data.data.authorizationToken;
              wx.setStorageSync("token", token);
              onUserLogin(token);
              console.log("authorization", token);
            },
            fail(err) {
              console.log("請(qǐng)求異常", err);
            },
          });
        };
        const onUserLogin = (token) => {
          getApp().globalData.token = token;
          wx.showToast({
            title: "登錄成功了",
          });
        };
        //必須進(jìn)行session是否過(guò)期檢查,不然會(huì)出現(xiàn)第一次點(diǎn)擊登錄,服務(wù)器報(bào)Illegal Buffer
        //的錯(cuò)誤,但是第二次點(diǎn)擊登錄正常。
        wx.checkSession({
          success: (res) => {
            // session_key 未過(guò)期,并且在本生命周期一直有效
            console.log("在登陸中");
            let token = wx.getStorageSync("token");
            if (token) onUserLogin(token);
          },
          fail: (res) => {
            // session_key已經(jīng)失效,需要重新執(zhí)行登錄流程
            wx.login({
              success(res0) {
                if (res0.code) {
                  requestLoginApi(res0.code);
                } else {
                  console.log("登錄失敗!" + res0.errMsg);
                }
              },
            });
          },
        });
      },
    });
  },
});

#針對(duì)登入程式碼可以做哪些最佳化?

對(duì)於一個(gè)軟體,就程式碼層面而言,需要追求最基本的幾個(gè)面向(遠(yuǎn)不止這些,但是先姑且先做個(gè)好這些吧):

  • 可維護(hù)性(maintainability)

    所謂的「維護(hù)」無(wú)外乎就是修改bug、修改舊的程式碼、新增新的程式碼之類的工作。所謂「程式碼易??維護(hù)」就是指,在不破壞原有程式碼設(shè)計(jì)、不引入新的 bug 的情況下,能夠快速地修改或新增程式碼。所謂「程式碼不易維護(hù)」就是指,修改或新增程式碼需要冒著極大的引入新 bug 的風(fēng)險(xiǎn),並且需要花費(fèi)很長(zhǎng)的時(shí)間才能完成。

  • 可讀性(readability)

    軟體設(shè)計(jì)大師Martin Fowler 曾經(jīng)說(shuō)過(guò):「Any fool can write code that a computer can understand. Good programmers write code that humans can understand.」翻譯成中文就是:「任何傻瓜都會(huì)寫電腦能理解的程式碼。好的程式設(shè)計(jì)師能夠編寫人能夠理解的程式碼。」Google 內(nèi)部甚至專門有個(gè)認(rèn)證就叫作Readability。只有拿到這個(gè)認(rèn)證的工程師,才有資格在 code review 的時(shí)候,就批準(zhǔn)別人提交代碼。可見程式碼的可讀性有多重要,畢竟,程式碼被閱讀的次數(shù)遠(yuǎn)遠(yuǎn)超過(guò)被編寫和執(zhí)行的次數(shù)。我們需要看程式碼是否符合編碼規(guī)範(fàn)、命名是否達(dá)意、註解是否詳盡、函數(shù)是否長(zhǎng)短適當(dāng)、模組劃分是否清晰、是否符合高內(nèi)聚低耦合等等。

  • 可擴(kuò)充性(extensibility)

    可擴(kuò)充性也是一個(gè)評(píng)價(jià)程式碼品質(zhì)非常重要的標(biāo)準(zhǔn)。程式碼預(yù)留了一些功能擴(kuò)充點(diǎn),你可以把新功能程式碼,直接插到擴(kuò)充點(diǎn)上,而不需要因?yàn)橐黾右粋€(gè)功能而大動(dòng)幹戈,改動(dòng)大量的原始程式碼。

  • 可重複使用性(reusability)

    代碼的可復(fù)用性可以簡(jiǎn)單地理解為,盡量減少重復(fù)代碼的編寫,復(fù)用已有的代碼。

那么接下來(lái)就來(lái)優(yōu)化一下代碼吧:

模塊化

可以把登錄的代碼模塊化,代碼如下:

// lib/login.js
function loginWithCallback(cb) {
  // 推薦使用wx.getUserProfile獲取用戶信息,開發(fā)者每次通過(guò)該接口獲取用戶個(gè)人信息均需用戶確認(rèn)
  // 開發(fā)者妥善保管用戶快速填寫的頭像昵稱,避免重復(fù)彈窗
  wx.getUserProfile({
    desc: "用于完善會(huì)員資料", // 聲明獲取用戶個(gè)人信息后的用途,后續(xù)會(huì)展示在彈窗中,請(qǐng)謹(jǐn)慎填寫
    success: (res) => {
      let { userInfo, encryptedData, iv } = res;
      const requestLoginApi = (code) => {
        // 發(fā)起網(wǎng)絡(luò)請(qǐng)求
        wx.request({
          url: "http://localhost:3000/user/weixin-login",
          method: "POST",
          header: {
            "content-type": "application/json",
          },
          data: {
            code,
            userInfo,
            encryptedData,
            iv,
          },
          success(res) {
            console.log("請(qǐng)求成功", res.data);
            let token = res.data.data.authorizationToken;
            wx.setStorageSync("token", token);
            onUserLogin(token);
            console.log("authorization", token);
          },
          fail(err) {
            console.log("請(qǐng)求異常", err);
          },
        });
      };

      const onUserLogin = (token) => {
        getApp().globalData.token = token;
        wx.showToast({
          title: "登錄成功了",
        });
        if (cb && typeof cb == "function") cb(token);
      };
      wx.checkSession({
        success: (res) => {
          // session_key 未過(guò)期,并且在本生命周期一直有效
          console.log("在登陸中");
          let token = wx.getStorageSync("token");
          if (token) onUserLogin(token);
        },
        fail: (res) => {
          // session_key已經(jīng)失效,需要重新執(zhí)行登錄流程
          wx.login({
            success(res0) {
              if (res0.code) {
                requestLoginApi(res0.code);
              } else {
                console.log("登錄失敗!" + res0.errMsg);
              }
            },
          });
        },
      });
    },
  });
}

export default loginWithCallback;

Promise化

回調(diào)地獄問(wèn)題,不利于代碼的閱讀,所以接下來(lái)我們基于Promise進(jìn)行代碼優(yōu)化。有了 Promise 對(duì)象,就可以將異步操作以同步操作的流程表達(dá)出來(lái),避免了層層嵌套的回調(diào)函數(shù)。此外,Promise 對(duì)象提供統(tǒng)一的接口,使得控制異步操作更加容易。

Promise的幾個(gè)方法簡(jiǎn)介

方法名稱說(shuō)明
#Promise.prototype.then 方法傳回的是一個(gè)新的Promise 對(duì)象,因此可以採(cǎi)用鍊式寫法。這種設(shè)計(jì)使得嵌套的非同步操作,可以被很容易得改寫,從回呼函數(shù)的"橫向發(fā)展"改為"向下發(fā)展"。
Promise.prototype.catch#是Promise.prototype.then(null, rejection) 的別名,用於指定發(fā)生錯(cuò)誤時(shí)的回調(diào)函數(shù)。 Promise 物件的錯(cuò)誤具有"冒泡"性質(zhì),會(huì)一直向後傳遞,直到被捕獲為止。也就是說(shuō),錯(cuò)誤總是會(huì)被下一個(gè) catch 語(yǔ)句捕捉。
Promise.prototype.finally#方法傳回一個(gè)Promise。在promise結(jié)束時(shí),無(wú)論結(jié)果是fulfilled或是rejected,都會(huì)執(zhí)行指定的回呼函數(shù)。這為在Promise是否成功完成後都需要執(zhí)行的程式碼提供了一種方式。
Promise.all這避免了同樣的語(yǔ)句需要在then()catch()中各寫一次的情況。 Promise.all 方法用於將多個(gè) Promise 實(shí)例,包裝成一個(gè)新的 Promise 實(shí)例。 Promise.all 方法接受一個(gè)陣列作為參數(shù),var p = Promise.all([p1,p2,p3]);p1、p2、p3 都是 Promise 物件的實(shí)例。 (Promise.all 方法的參數(shù)不一定是數(shù)組,但是必須具有 iterator 接口,且返回的每個(gè)成員都是 Promise 實(shí)例。)p 的狀態(tài)由 p1、p2、p3 決定,分成兩種情況。?(1)只有p1、p2、p3的狀態(tài)都變成fulfilled,p的狀態(tài)才會(huì)變成fulfilled,此時(shí)p1、p2、p3的回傳值組成一個(gè)數(shù)組,傳遞給p的回呼函數(shù)。 (2)只要p1、p2、p3之中有一個(gè)被rejected,p的狀態(tài)就變成rejected,此時(shí)第一個(gè)被reject的實(shí)例的回傳值,就會(huì)傳遞給p的回呼函數(shù)。
Promise.racePromise.race 方法同樣是將多個(gè) Promise 實(shí)例,包裝成新的 Promise 實(shí)例。 var p = Promise.race([p1,p2,p3]);上面程式碼中,只要p1、p2、p3之中有一個(gè)實(shí)例率先改變狀態(tài),p的狀態(tài)就跟著改變。那個(gè)率先改變的Promise實(shí)例的回傳值,就傳遞給p的回傳值。
Promise.any接收一個(gè)Promise可迭代對(duì)象,只要其中的一個(gè) promise 成功,就返回那個(gè)已經(jīng)成功的 promise 。所有子實(shí)例都處?kù)秗ejected狀態(tài),總的promise才會(huì)處?kù)秗ejected狀態(tài)。
Promise.allSettled#回傳一個(gè)在所有給定的promise都已經(jīng)fulfilledrejected後的promise,並帶有一個(gè)物件數(shù)組,每個(gè)物件表示對(duì)應(yīng)的promise結(jié)果。相較之下,Promise.all() 更適合彼此相互依賴或在其中任何一個(gè)reject時(shí)立即結(jié)束。

小程序API接口Promise化并且把需要登錄的調(diào)用接口模塊化

1、安裝插件。請(qǐng)先查看npm支持文檔。

npm install --save miniprogram-api-promise

2、在微信開發(fā)者工具右方詳情中勾選使用npm模塊,并在菜單欄工具中點(diǎn)擊構(gòu)建npm。

3、初始化代碼。

// app.js
import {promisifyAll} from &#39;miniprogram-api-promise&#39;
import login from "../lib/login";
const wxp ={}
promisifyAll(wx,wxp)
// 需要token的請(qǐng)求統(tǒng)一處理登錄和設(shè)置header,并且處理錯(cuò)誤信息
wxp.requestNeedLogin = async function (args) {
  let token = wx.getStorageSync("token");
  if (!token) {
    token = await loginWithPromise();
  }
  if (!args.header) args.header = {};
  args.header["Authorization"] = `Bearer ${token}`;
  return wxp.request(args).catch(console.error);
};
// app.js
App({
  wxp:wxp,
});

4、改寫login.js代碼

// lib/login.js
function login() {
  return new Promise((resolve, reject) => {
    // 推薦使用wx.getUserProfile獲取用戶信息,開發(fā)者每次通過(guò)該接口獲取用戶個(gè)人信息均需用戶確認(rèn)
    // 開發(fā)者妥善保管用戶快速填寫的頭像昵稱,避免重復(fù)彈窗
    wx.getUserProfile({
      desc: "用于完善會(huì)員資料", // 聲明獲取用戶個(gè)人信息后的用途,后續(xù)會(huì)展示在彈窗中,請(qǐng)謹(jǐn)慎填寫
       success:async (res0) => {
        let {
          userInfo,
          encryptedData,
          iv
        } = res0;
        const app = getApp();
        try {
          app.wxp.checkSession();
        } catch (err) {
          reject(err);
        }
        let token = wx.getStorageSync("token");
        if (!token) {
          let res1 = await app.wxp.login().catch(err => reject(err));
          let code = res1.code;
          let res = await app.wxp.request({
            url: "http://localhost:3000/user/weixin-login",
            method: "POST",
            header: {
              "content-type": "application/json",
            },
            data: {
              code,
              userInfo,
              encryptedData,
              iv,
            }
          }).catch(err => reject(err));
          token = res.data.data.authorizationToken;
          wx.setStorageSync("token", token);
          app.globalData.token = token;
          wx.showToast({
            title: "登錄成功了",
          });
          resolve(token);
        }
      },
    });
  })
}

export default login;

5、調(diào)用代碼

<view class="container page-head">
  <text class="page-section__title">需要登錄的請(qǐng)求調(diào)用</text>
  <view class="btn-area">
    <button bindtap="request1" type="primary">請(qǐng)求1</button>
    <button bindtap="request2" type="primary">請(qǐng)求2</button>
  </view>
</view>
// pages/index.js
Page({
  /**
   * 頁(yè)面的初始數(shù)據(jù)
   */
  data: {},
  request1() {
    getApp().wxp.requestNeedLogin({
        url: "http://localhost:3000/user/home?name=andying",
      }).then(console.log)
  },
  request2() {
    getApp().wxp.requestNeedLogin({
        url: "http://localhost:3000/user/home?name=eva",
      }).then(console.log)
  },
});

【相關(guān)學(xué)習(xí)推薦:小程序開發(fā)教程

以上是淺析小程式怎麼實(shí)現(xiàn)登入功能的詳細(xì)內(nèi)容。更多資訊請(qǐng)關(guān)注PHP中文網(wǎng)其他相關(guān)文章!

本網(wǎng)站聲明
本文內(nèi)容由網(wǎng)友自願(yuàn)投稿,版權(quán)歸原作者所有。本站不承擔(dān)相應(yīng)的法律責(zé)任。如發(fā)現(xiàn)涉嫌抄襲或侵權(quán)的內(nèi)容,請(qǐng)聯(lián)絡(luò)admin@php.cn

熱AI工具

Undress AI Tool

Undress AI Tool

免費(fèi)脫衣圖片

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅(qū)動(dòng)的應(yīng)用程序,用於創(chuàng)建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費(fèi)的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費(fèi)的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強(qiáng)大的PHP整合開發(fā)環(huán)境

Dreamweaver CS6

Dreamweaver CS6

視覺(jué)化網(wǎng)頁(yè)開發(fā)工具

SublimeText3 Mac版

SublimeText3 Mac版

神級(jí)程式碼編輯軟體(SublimeText3)

小紅書怎麼登入以前的帳號(hào)?它換綁後原來(lái)號(hào)碼遺失了怎麼辦? 小紅書怎麼登入以前的帳號(hào)?它換綁後原來(lái)號(hào)碼遺失了怎麼辦? Mar 21, 2024 pm 09:41 PM

隨著社群媒體的快速發(fā)展,小紅書成為許多年輕人分享生活、探索新產(chǎn)品的熱門平臺(tái)。在使用過(guò)程中,有時(shí)使用者可能會(huì)遇到登入先前帳號(hào)的困難。本文將詳細(xì)探討如何解決小紅書登入舊帳號(hào)的問(wèn)題,以及如何應(yīng)對(duì)更換綁定後可能遺失原帳號(hào)的情況。一、小紅書怎麼登入以前的帳號(hào)? 1.找回密碼登入如果長(zhǎng)時(shí)間未登入小紅書,可能導(dǎo)致帳號(hào)被系統(tǒng)回收。為了恢復(fù)存取權(quán)限,你可以嘗試透過(guò)找回密碼的方式重新登入帳號(hào)。操作步驟如下:(1)開啟小紅書App或官網(wǎng),點(diǎn)選「登入」按鈕。 (2)選擇「找回密碼」。 (3)輸入你註冊(cè)帳號(hào)時(shí)所使用的手機(jī)號(hào)碼

wallpaperengine登入別的號(hào)碼後下載別人的桌布怎麼辦 wallpaperengine登入別的號(hào)碼後下載別人的桌布怎麼辦 Mar 19, 2024 pm 02:00 PM

當(dāng)你在自己電腦上登過(guò)別人steam帳號(hào)之後,剛好這個(gè)別人的帳號(hào)也有wallpaper軟體,切換回自己帳號(hào)之後steam就會(huì)自動(dòng)下載別人帳號(hào)訂閱的桌布,使用者可以透過(guò)關(guān)閉steam雲(yún)端同步解決。 wallpaperengine登入別的號(hào)碼後下載別人的桌布怎麼辦1、登陸你自己的steam帳號(hào),在設(shè)定裡面找到雲(yún)端同步,關(guān)閉steam雲(yún)端同步。 2.登陸你之前登陸的別人的steam帳號(hào),打開wallpaper創(chuàng)意工坊,找到訂閱內(nèi)容,然後取消全部訂閱。 (以後防止找不到壁紙,可以先收藏再取消訂閱)3、切換回自己的stea

快手電腦版怎麼登入-快手電腦版的登入方法 快手電腦版怎麼登入-快手電腦版的登入方法 Mar 04, 2024 pm 03:30 PM

近日有一些小夥伴諮詢小編快手電腦版怎麼登入?下面就為大家?guī)?lái)了快手電腦版的登入方法,有需要的小夥伴可以來(lái)了解了解哦。第一步:先在電腦的瀏覽器上百度搜尋快手官網(wǎng)。第二步:在搜尋結(jié)果清單裡面選取第一條。第三步:進(jìn)入快手官網(wǎng)主頁(yè)面後,點(diǎn)選影片的選項(xiàng)。第四步:點(diǎn)選右上角的使用者頭像。步驟五:在彈出的登入選單裡面點(diǎn)選二維碼登入。步驟六:之後打開手機(jī)上的快手,點(diǎn)選左上角的圖示。第七步:點(diǎn)選二維碼標(biāo)誌。第八步:在我的二維碼介面點(diǎn)擊右上角的掃描圖示之後,掃描電腦上的二維碼即可。第九步:最後電腦版的快手就登入成

《陰陽(yáng)師》茨木童子典藏皮膚登入即領(lǐng),禪心雲(yún)外鏡新造型即將上線! 《陰陽(yáng)師》茨木童子典藏皮膚登入即領(lǐng),禪心雲(yún)外鏡新造型即將上線! Jan 05, 2024 am 10:42 AM

山野間萬(wàn)鬼嘶鳴,隱沒(méi)兵刃交接之聲,越嶺奔赴而來(lái)的鬼將,心中戰(zhàn)意洶湧,以炎火為號(hào),率百鬼衝鋒迎戰(zhàn)。 【熾焱百煉?茨木童子典藏皮膚上線】鬼角熾焰怒燃,鎏金眼眸迸發(fā)桀駿戰(zhàn)意,白玉甲片裝飾戰(zhàn)袍,彰顯大妖不羈狂放的氣勢(shì)。雪白飄揚(yáng)的袖擺上,赤焰攀附交織,金紋烙印其中,燃點(diǎn)一片緋艷妖異色彩。妖力凝聚而成的鬼火咆哮而至,烈焰令群巒為之震動(dòng),煉獄間歸來(lái)的妖鬼啊,一同懲戒進(jìn)犯之人吧。 【專屬動(dòng)態(tài)頭像框?熾焱百煉】【專屬插畫?焰火將魂】【傳記鑑賞】【獲取方式】茨木童子典藏皮膚·熾焱百煉將於12月28日維護(hù)後上架皮膚商店,

Discuz後臺(tái)登入問(wèn)題解決方法大揭秘 Discuz後臺(tái)登入問(wèn)題解決方法大揭秘 Mar 03, 2024 am 08:57 AM

Discuz後臺(tái)登入問(wèn)題解決方法大揭秘,需要具體程式碼範(fàn)例隨著網(wǎng)路的快速發(fā)展,網(wǎng)站建置變得越來(lái)越普遍,而Discuz作為一款常用的論壇建站系統(tǒng),受到了許多站長(zhǎng)的青睞。然而,正是因?yàn)槠涔δ軓?qiáng)大,有時(shí)候我們?cè)谑褂肈iscuz的過(guò)程中會(huì)遇到一些問(wèn)題,例如後臺(tái)登入問(wèn)題。今天,我們就來(lái)大揭秘Discuz後臺(tái)登入問(wèn)題的解決方法,並且提供具體的程式碼範(fàn)例,希望能幫助到有需要

小紅書只記得帳號(hào)怎麼登入?只記得帳號(hào)怎麼找回來(lái)? 小紅書只記得帳號(hào)怎麼登入?只記得帳號(hào)怎麼找回來(lái)? Mar 23, 2024 pm 05:31 PM

小紅書如今已經(jīng)融入了許多人的日常生活,其豐富的內(nèi)容和便捷的操作方式讓使用者樂(lè)此不疲。有時(shí)候,我們可能會(huì)忘記帳號(hào)密碼,只記得帳號(hào)而無(wú)法登入確實(shí)讓人感到困擾。一、小紅書只記得帳號(hào)怎麼登入?當(dāng)忘記密碼時(shí),我們可以透過(guò)手機(jī)驗(yàn)證碼的方式登入小紅書。具體操作如下:1.開啟小紅書App或網(wǎng)頁(yè)版小紅書;2.點(diǎn)選「登入」按鈕,選擇「帳號(hào)密碼登入」;3.點(diǎn)選「忘記密碼?」按鈕;4.輸入你的帳號(hào),點(diǎn)選「下一步」;5.系統(tǒng)會(huì)發(fā)送驗(yàn)證碼到你的手機(jī),輸入驗(yàn)證碼後點(diǎn)選「確定」;6.設(shè)定新的密碼並確認(rèn)。你也可以透過(guò)第三方帳號(hào)(如

百度網(wǎng)盤網(wǎng)頁(yè)版怎麼進(jìn)?百度網(wǎng)盤網(wǎng)頁(yè)版登入入口 百度網(wǎng)盤網(wǎng)頁(yè)版怎麼進(jìn)?百度網(wǎng)盤網(wǎng)頁(yè)版登入入口 Mar 13, 2024 pm 04:58 PM

  百度網(wǎng)盤不僅能儲(chǔ)存各種軟體資源,還能分享給別人,支援多端同步,如果你的電腦沒(méi)有下載客戶端,可以選擇進(jìn)入網(wǎng)頁(yè)版使用。那麼百度網(wǎng)盤網(wǎng)頁(yè)版要怎麼登入呢?下面就來(lái)看看詳細(xì)介紹?! “俣染W(wǎng)盤網(wǎng)頁(yè)版登入入口:https://pan.baidu.com(複製連結(jié)至瀏覽器開啟)  軟體介紹  1、分享  提供文件分享功能,使用者將文件整理,分享給需要的小夥伴?! ?、雲(yún)端  不佔(zhàn)用太多內(nèi)存,大多數(shù)檔案都保存在雲(yún)端,有效節(jié)省電腦空間?! ?、相簿  支援雲(yún)相簿功能,將照片匯入到雲(yún)盤中,然後整理,方便大家查看?! ?/p>

實(shí)作微信小程式中的卡片翻轉(zhuǎn)特效 實(shí)作微信小程式中的卡片翻轉(zhuǎn)特效 Nov 21, 2023 am 10:55 AM

實(shí)作微信小程式中的卡片翻轉(zhuǎn)特效在微信小程式中,實(shí)現(xiàn)卡片翻轉(zhuǎn)特效是一種常見的動(dòng)畫效果,可以提升使用者體驗(yàn)和介面互動(dòng)的吸引力。以下將具體介紹如何在微信小程式中實(shí)現(xiàn)卡片翻轉(zhuǎn)的特效,並提供相關(guān)程式碼範(fàn)例。首先,需要在小程式的頁(yè)面佈局檔案中定義兩個(gè)卡片元素,一個(gè)用於顯示正面內(nèi)容,一個(gè)用於顯示背面內(nèi)容,具體範(fàn)例程式碼如下:&lt;!--index.wxml--&gt;&l

See all articles