Taro跨段開發探索8——promise等待請求與小程式父子元件傳值探索

語言: CN / TW / HK

一起養成寫作習慣!這是我參與「掘金日新計劃 · 4 月更文挑戰」的第14天,點選檢視活動詳情

前言

昨天我們實現了小程式的登入攔截與白名單的處理,今天我們先優化一下昨天留下的坑,然後來編寫一個父子元件間傳遞值得方法

關於在請求未完成的時候,傳遞token為空的問題處理——promise處理

我將從以下幾個方面仔細解釋一下原因和解決方案

問題產生的原因

我們按照一開始的方法呼叫後端介面的時候整個過程是非同步的。此時我們在return值的時候,後端沒有處理完我們的請求,我們的值不會發生變化

解決的方法——promise

我們在封裝統一的request時,已經使用promise封裝了,這裡我們也使用promise解決非同步請求未執行方法就向下執行的問題,大家如果不瞭解promise的話,可以自己查一下ES6的新特性,瞭解一下promise

最終的request/index.tsx

`` import Taro from "@tarojs/taro"; const white_res_code = [200, 10001, 10002]; const white_uri = ["/auth/login"]; import { loginByCode } from "../api/user"; function getTokenByApi() { return new Promise((resolve) => { Taro.login({ success: (res) => { loginByCode(res.code).then((res) => { resolve(res["token"]); }); }, }); }); } async function request(url, data, method): Promise<any> { let notNeedTokenflag = white_uri.filter((item) => url.includes(item)).length > 0; let token = Taro.getStorageSync("token"); if (!notNeedTokenflag && (!token || token === "")) { token = await getTokenByApi(); Taro.setStorageSync("token", token); } const header = { "content-type": "application/json", }; if (!notNeedTokenflag) { header["Authorization"] =Bearer ${token}`; } return new Promise((resolve) => { let retryCount = Taro.getStorageSync("returCount") || 0; if (retryCount >= 10) { setTimeout(() => { Taro.removeStorageSync("returCount"); }, 5000); return Taro.showToast({ title: "您已被限制5秒內不可以訪問介面", icon: "none", }); } Taro.request({ url, data, method, header, }) .then((res) => { if (res.statusCode === 200) { const backEndRes = res.data; const resCode = backEndRes.code; if (!white_res_code.includes(resCode)) { switch (resCode) { case 500: return Taro.showToast({ title: "請求失敗,系統異常:" + backEndRes.msg, icon: "none", }); case 401: Taro.removeStorageSync("token"); Taro.setStorageSync("returCount", retryCount + 1); request(url, data, method); return Taro.showToast({ title: "請求失敗,請您登陸:" + backEndRes.msg, icon: "none", }); case 403: Taro.removeStorageSync("token"); Taro.setStorageSync("returCount", retryCount + 1); request(url, data, method); return Taro.showToast({ title: "請求失敗,暫無許可權:" + backEndRes.msg, icon: "none", });

          default:
            return Taro.showToast({
              title: "請求失敗:" + res.data.error,
              icon: "none",
            });
        }
      } else {
        resolve(backEndRes.data);
      }
      resolve(res.data);
    } else {
      Taro.showToast({ title: "請求失敗:" + res.data.error, icon: "none" });
    }
  })
  .catch((err) => {
    Taro.showToast({ title: "網路錯誤,提示:" + err.errMsg, icon: "none" });
  });

}); } function get(url) { return request(url, null, "GET"); }

function post(url, data) { return request(url, data, "POST"); } function del(url) { return request(url, null, "DELETE"); } function put(url, data) { return request(url, data, "POST"); } export { get, post, del, put }; ``` 簡單解釋一下 - 在request方法前新增async標識它為非同步函式 - 在呼叫獲取token的地方新增await方法 - 修改獲取token的方法,使其成為返回promise的方法

下面我們主要講一下今天比較重點的內容,父子元件之間傳值

業務場景

我們有很多的業務場景需要父子元件之間傳值。比較常見的就是父元件獲取出列表之後,點開字元件時傳入父元件來獲取詳情。在子元件更新完對應的資料之後,需要重新整理父元件或者從父元件中將子元件關閉。

先看看vue常用的方式

  • 通過父元件ref到子元件然後呼叫子元件的方法賦值,例如this.$refs("child").open(id)
  • 通過子元件的prop屬性傳參,例如<child id={chooseData.id}>
  • 狀態管理器傳參,這種傳參方式比較少,但是一般複雜度比較高的專案往往用的比較多

使用基於react的父子元件傳參的實現

購物車index頁面 import { View, Text } from "@tarojs/components"; import { useEffect, useState } from "react"; import ShopCartItem from "./shop-cart-item"; import "./index.scss"; export default function ShopCart() { const [shopCartList, setShopCartList] = useState([]); useEffect(() => { setShopCartList([ { id: "1", name: "第1個商品", price: 100, num: 4 }, { id: "2", name: "第2個商品", price: 200, num: 3 }, { id: "3", name: "第3個商品", price: 300, num: 2 }, { id: "4", name: "第4個商品", price: 400, num: 1 }, ]); }, []); return ( <View className="shop-cart"> {shopCartList.map((item,index) => (<ShopCartItem item={item}></ShopCartItem>) )} <Text>共{shopCartList.length}條資料</Text> </View> ); } 購物車item頁面 ``` import { View, Text } from "@tarojs/components"; import { Component } from "react"; import "./index.scss"; class ShopCartItem extends Component { constructor(props) { super(props); item: { } } render() { const item = this.props["item"]; return ( 商品名稱{item.name} ); } }

export default ShopCartItem;

```

結語

每天的時間都是不太充足,每天都徘徊在鴿了的邊緣,今天先完成父資料傳子元件的需求吧,明天補充一下子傳父的程式碼(其實開發了,但是功能沒實現)。歡迎大家多多關注點贊!