Skip to content

Commit

Permalink
Merge pull request #138 from j10ccc/feat/new-request-function
Browse files Browse the repository at this point in the history
feat(service): new request implementation
  • Loading branch information
j10ccc authored Oct 22, 2024
2 parents 0e13a99 + 3ae3fc0 commit 02684e9
Show file tree
Hide file tree
Showing 15 changed files with 308 additions and 20 deletions.
2 changes: 1 addition & 1 deletion project.config.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"appid": "wxd4b11753654a636f",
"setting": {
"urlCheck": false,
"es6": false,
"es6": true,
"enhance": false,
"postcss": false,
"preloadBackgroundData": false,
Expand Down
3 changes: 2 additions & 1 deletion src/hooks/index.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import useTimeInstance from "./useTimeString";
import useRequest from "./useRequest";
import useRequest, { useRequestNext } from "./useRequest";
import useDarkMode from "./useDarkMode";

export {
useTimeInstance,
useRequest,
useRequestNext,
useDarkMode
};
74 changes: 73 additions & 1 deletion src/hooks/useRequest.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@

import Taro from "@tarojs/taro";
import { onMounted, ref } from "vue";
import { onMounted, ref, shallowRef } from "vue";

interface RequestConfigType<TData extends TaroGeneral.IAnyObject, TParams> {
/** 是否手动发起请求 */
Expand Down Expand Up @@ -36,6 +36,7 @@ interface RequestConfigType<TData extends TaroGeneral.IAnyObject, TParams> {
}

/**
* @deprecated
* 封装请求成 hook
*
* 为请求函数扩展
Expand Down Expand Up @@ -94,3 +95,74 @@ const useRequest = <TData extends TaroGeneral.IAnyObject, TParams>(
};

export default useRequest;

type UseRequestOptions<Data, Params> = {
/** Promise 还未 fulfilled 时,给 `data` 的初始值 */
initialData: Data;
/** 自动触发请求,以及调用 `run` 函数不传参数时,默认给请求函数传入的参数 */
defaultParams?: Params;
/** 是否手动触发请求, 默认为 false */
manual?: boolean;
/** 最短加载时间,默认为 0ms,在有加载动画效果时防止渲染闪屏 */
minLoadingTime?: number;
/** 在执行 Promise 前,将 `data` 重置为 `initialData`,默认为 false */
resetOnRun?: boolean;
onSuccess?: (data: Data) => void;
onError?: (error: unknown) => void;
};

const promiseTimeout = (ms: number) => {
return new Promise(resolve => {
setTimeout(resolve, ms);
});
};

export function useRequestNext<State, Params extends Record<string, any>>(
promise: (params?: Params) => Promise<State>,
options: UseRequestOptions<State, Params>
) {
const {
initialData,
defaultParams,
manual = false,
minLoadingTime = 0,
resetOnRun = false,
onSuccess,
onError
} = options ?? {};

const loading = ref(false);
const data = ref(initialData);
const error = shallowRef<unknown | undefined>(undefined);

async function run(params?: Params) {
loading.value = true;
error.value = undefined;
if (resetOnRun) data.value = initialData;

// 用 `allSettled` 而不用 try-catch 是为了 Delay 也作用到异常状态
const delayedPromise = Promise.allSettled([
promise(params ?? defaultParams),
promiseTimeout(minLoadingTime)
]);
const [promiseResult] = await delayedPromise;
if (promiseResult.status === "fulfilled") {
data.value = promiseResult.value;
onSuccess?.(promiseResult.value);
} else {
error.value = promiseResult.reason;
onError?.(promiseResult.reason);
}

loading.value = false;
};

if (!manual) run();

return {
loading,
data,
error,
run
};
}
12 changes: 0 additions & 12 deletions src/services/api/apiList.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,16 +65,4 @@ const api = {
}
};

const defDevHost = "http://0.0.0.0:8080";
function appendHost(api: any) {
for (const key in api)
if (Object.prototype.hasOwnProperty.call(api, key))
if (api[key] instanceof Object) appendHost(api[key]);
else
api[key] = process.env.HOST
? process.env.HOST + api[key]
: defDevHost + api[key];
}

appendHost(api);
export { api };
3 changes: 3 additions & 0 deletions src/services/api/codes.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
/**
* @deprecated
*/
export const ServerCode = {
OK: 1,

Expand Down
5 changes: 4 additions & 1 deletion src/services/request.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,16 @@ const globalConfig: Partial<Taro.request.Option> = {
timeout: 12 * 1000
};

/**
* @deprecated
*/
const request = <TData extends TaroGeneral.IAnyObject | any> (
url: string,
config: Omit<Taro.request.Option, "url">
) => {
return Taro.request<IResponse<TData>>({
...globalConfig,
url,
url: process.env.HOST + url,
...config
});

Expand Down
1 change: 1 addition & 0 deletions src/services/services/authService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import errCodeHandler from "../utils/errHandler";
import { ServerCode } from "../api/codes";

/**
* @deprecated
* 与微信建立链接,获取 session
* 场景: 发送带 session 的请求 postWithSession,打开小程序页面
*/
Expand Down
6 changes: 5 additions & 1 deletion src/services/utils/errHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@ import { ServerCode } from "../api/codes";
import Taro from "@tarojs/taro";
import store, { serviceStore } from "@/store";

// comment: 微信相关登录异常处理
/**
* @deprecated
* 微信相关登录异常处理
* TODO: 迁移处理逻辑至具体的业务模块
*/
export default async function errCodeHandler(code: number, showModal = true) {
console.error("Error code", code);
if (showModal)
Expand Down
3 changes: 3 additions & 0 deletions src/services/utils/session.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { LoginByTaro } from "../services/authService";
import { ServerCode } from "../api/codes";

/**
* @deprecated
* 调用 fetch 带上 session 发送请求
*
* 一般通过 `updateDateStateWithSession` 调用
Expand Down Expand Up @@ -42,6 +43,7 @@ async function postWithSession(
}

/**
* @deprecated
* 检查有无 session
* @returns 状态
*/
Expand All @@ -50,6 +52,7 @@ function checkSession(): boolean {
}

/**
* @deprecated
* 检查 session 对应的微信用户有没有激活记录
* @returns 状态
*/
Expand Down
2 changes: 2 additions & 0 deletions src/services/utils/updateDateState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { ServerCode } from "../api/codes";
import errCodeHandler from "./errHandler";

/**
* @deprecated
* 无 session 请求更新全局状态,系统请求专用
* @param api
* @param data
Expand Down Expand Up @@ -34,6 +35,7 @@ async function updateDateState(
}

/**
* @deprecated
* 带 session 发送请求,并更新状态
* @param api
* @param data
Expand Down
10 changes: 8 additions & 2 deletions src/utils/fetch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ interface FetchResult extends Taro.request.SuccessCallbackResult<any> {
cookies?: string[];
}

/**
* @deprecated
*/
function get(url: string, cookies?: ICookie[]): Promise<FetchResult> {
const header = cookies
? {
Expand All @@ -17,7 +20,7 @@ function get(url: string, cookies?: ICookie[]): Promise<FetchResult> {
};
return new Promise((resolve, reject) => {
Taro.request({
url: url,
url: process.env.HOST + url,
header: header,
mode: "cors",
success: (res) => {
Expand All @@ -31,6 +34,9 @@ function get(url: string, cookies?: ICookie[]): Promise<FetchResult> {
});
}

/**
* @deprecated
*/
function postJson(
url: string,
data: any,
Expand All @@ -47,7 +53,7 @@ function postJson(
};

Taro.request({
url: url,
url: process.env.HOST + url,
data: data ? data : undefined,
header: header,
method: "POST",
Expand Down
10 changes: 9 additions & 1 deletion src/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ import timeUtils from "./time";
import type { ICookie } from "./cookie";
import type { FetchResult } from "./fetch";
import { debounce } from "./debounce";
import request from "./request/requestImpl";
import RequestError, { ServiceErrorCode, MPErrorCode } from "./request/requestError";
import CookieUtils from "./request/cookie";

export {
ICookie,
Expand All @@ -20,5 +23,10 @@ export {
checkBind,
checkNotification,
timeUtils,
debounce
debounce,
request,
ServiceErrorCode,
MPErrorCode,
RequestError,
CookieUtils
};
66 changes: 66 additions & 0 deletions src/utils/request/cookie.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import Taro from "@tarojs/taro";
import { persistedStateStorage } from "../storage";
import RequestError, { MPErrorCode, ServiceErrorCode } from "./requestError";
import { api } from "@/services";

export default class CookieUtils {
private static keyInStorage = "__cookie__";
private static cookie: string = "";

/**
* 从内存、持久化储存中获取 Cookie
*
* 若两处都没有 Cookie,则触发登录流程获取新的 Cookie
*/
public static async get(): Promise<string> {
if (!this.cookie) {
const cookieInStore = persistedStateStorage.getItem(this.keyInStorage);
this.cookie = cookieInStore || await this.refresh();
}

return this.cookie;
}

/**
* 登录以获取服务端 Cookie
*
* @throws {RequestError}
* @returns 新 Cookie
*/
public static async refresh(): Promise<string> {
try {
const { code, errMsg } = await Taro.login({ timeout: 3000 });
if (!code) {
console.error(new Error(errMsg));
return Promise.reject(
new RequestError({ message: errMsg, code: MPErrorCode.MP_LOGIN_ERROR_MISSING_WX_CODE })
);
}

const taroWrapped = await Taro.request<{ data: { user: any }, code: number }>({
url: process.env.HOST + api.user.login.wechat,
data: { code },
method: "POST"
});
const { data: realResponse, cookies } = taroWrapped;
if (realResponse && realResponse.code === ServiceErrorCode.OK) {
if (cookies && cookies.length > 0) {
const cookie = cookies[0]; // 现业务全局仅有一个 Cookie,所以取第一个
persistedStateStorage.setItem(this.keyInStorage, cookie);
return cookie;
}
return Promise.reject(
new RequestError({ message: "小程序登录失败", code: MPErrorCode.MP_LOGIN_ERROR_MISSING_COOKIE })
);
}
throw new Error(JSON.stringify(taroWrapped));
} catch (e) {
console.error(e);
throw new RequestError({ message: "小程序登录失败", code: MPErrorCode.MP_LOGIN_ERROR_UNKNOWN });
}
}

public static clear() {
persistedStateStorage.removeItem(this.keyInStorage);
}
}
37 changes: 37 additions & 0 deletions src/utils/request/requestError.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
export const MPErrorCode = {
MP_NETWORK_ERROR: Symbol("MP_NETWORK_ERROR"),
MP_LOGIN_ERROR_MISSING_WX_CODE: Symbol("MP_LOGIN_ERROR_MISSING_WX_CODE"),
MP_LOGIN_ERROR_MISSING_COOKIE: Symbol("MP_LOGIN_ERROR_MISSING_COOKIE"),
MP_LOGIN_ERROR_UNKNOWN: Symbol("MP_LOGIN_ERROR_UNKNOWN")
};

export enum ServiceErrorCode {
OK = 1,
NOT_ADMIN = 100403,

USER_ALREADY_EXISTED = 200508,
USER_USERNAME_PASSWORD_UNMATCHED = 200504,
USER_NOT_LOGIN = 200503,

SYSTEM_ERROR_1 = 200500,
SYSTEM_ERROR_2 = 200506,

ACTIVATION_SCHOOL_ID_OR_ID_NOT_EXIST_NOT_MATCH = 200510,
ACTIVATION_PASSWORD_LENGTH_ERROR = 200511,
ACTIVATION_PASSPORT_EXISTED = 200512,
ACTIVATION_SCHOOL_ID_ERROR = 200513
}

export default class RequestError extends Error {
public message: string;
public code: ServiceErrorCode | number | symbol;

constructor(props: {
message: string;
code: ServiceErrorCode | number | symbol;
}) {
super();
this.message = props.message;
this.code = props.code;
}
}
Loading

0 comments on commit 02684e9

Please sign in to comment.