Taro跨段开发探索8——promise等待请求与小程序父子组件传值探索

一起养成写作习惯!这是我参与「掘金日新计划 · 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 (
      <View className="shop-cart-item">
        <Text>商品名称{item.name}</Text>
      </View>
    );
  }
}

export default ShopCartItem;

复制代码

结语

每天的时间都是不太充足,每天都徘徊在鸽了的边缘,今天先完成父数据传子组件的需求吧,明天补充一下子传父的代码(其实开发了,但是功能没实现)。欢迎大家多多关注点赞!

猜你喜欢

转载自juejin.im/post/7086484265440903176
今日推荐