UNPKG

cve-connector

Version:
326 lines (267 loc) 7.47 kB
# 代码重构日志 ## 240619 获取云渲染实例的方法 getPixelStreamingInstance ### Before ```ts import axios from 'axios' import type { AxiosResponse } from 'axios' type PixelStreamingCode = '0' | '1' | '2' | '3' interface PixelStreamingData { Code: PixelStreamingCode Data: string | null Result: string } interface PixelStreamingQuery { ApplicationName: string } export function getPixelStreamingInstance(url: string): PixelStreamingPromise { return new Promise((resolve, reject) => { axios(url) .then((res: AxiosResponse<PixelStreamingData, PixelStreamingQuery>) => { const data: PixelStreamingData = res.data switch (data.Code) { case '0': { if (data.Data) { resolve(data.Data) } else { reject('Get Pixel Streaming Instance Failed!') } break } case '3': { reject(data) break } default: { setTimeout(() => { resolve(getPixelStreamingInstance(url)) }, 1000) } } }) .catch((error: unknown) => { reject(error) }) }) } ``` ### Step 1 减少依赖 插件中仅此处使用 axios 插件,决定改用 fetch 发送请求,减少依赖项。 ```ts import axios from 'axios' import type { AxiosResponse } from 'axios' interface PixelStreamingQuery { ApplicationName: string } axios(url) .then((res: AxiosResponse<PixelStreamingData, PixelStreamingQuery>) => { const data: PixelStreamingData = res.data // ... }) .catch((error: unknown) => { reject(error) }) ``` 以上代码改为: ```ts fetch(url) .then(async (response: Response) => response.json()) .then((data: PixelStreamingData) => { // ... }) .catch((error: unknown) => { reject(error) }) ``` ### Step 2 异步编程 基于异步函数改造代码,减少 Promise 链式调用。 ```ts export function getPixelStreamingInstance(url: string): PixelStreamingPromise { return new Promise((resolve, reject) => { fetch(url) .then(async (response: Response) => response.json()) .then((data: PixelStreamingData) => { switch (data.Code) { case '0': { if (data.Data) { resolve(data.Data) } else { reject('Get Pixel Streaming Instance Failed!') } break } case '3': { reject(data) break } default: { setTimeout(() => { resolve(getPixelStreamingInstance(url)) }, 1000) } } }) .catch((error: unknown) => { reject(error) }) }) } ``` - 将 resolve 改为 return data - 将 reject 改写为 throw error 以上代码逻辑改写为: ```ts export async function getPixelStreamingInstance(url: string): PixelStreamingPromise { const response = await fetch(url) const data: PixelStreamingData = await response.json() switch (data.Code) { case '0': { if (data.Data) { return data.Data } else { throw new Error('Get Pixel Streaming Instance Failed!') } } case '3': { throw new Error(data.Data) } default: { setTimeout(() => { return getPixelStreamingInstance(url) }, 1000) } } } ``` ### Step 3 分支拆解 弃用 switch 分支,减少缩进和嵌套。 ```ts switch (data.Code) { case '0': { if (data.Data) { return data.Data } else { throw new Error('Get Pixel Streaming Instance Failed!') } } case '3': { throw new Error(data.Data) } default: { setTimeout(() => { return getPixelStreamingInstance(url) }, 1000) } } ``` - 将异常检测的逻辑提前 - 简化计时器代码 - 将 return 后置,保证方法一定有返回值 将代码改为: ```ts if (!data.Data) { throw new Error('Get Pixel Streaming Instance Failed!') } if (data.Code === '3') { throw new Error(data.Data) } if (data.Code !== '0') { setTimeout(() => getPixelStreamingInstance(url), 1000) } return data.Data ``` ### Step 4 入参拆解 url 参数一般为 'http://127.0.0.1:8080/GetPixelStreamingInstance?ApplicationName=CveTemplate',格式其实是固定的,将参数拆解到最小单位,只需要传入 origin 及 name,并补充异常检测。 ```ts export async function getPixelStreamingInstance(url: string): PixelStreamingPromise { const response = await fetch(url) const data: PixelStreamingData = await response.json() // ... if (data.Code !== '0') { setTimeout(() => getPixelStreamingInstance(url), 1000) } return data.Data } ``` 以上代码改为: ```ts export async function requestInstance(url: string): PixelStreamingPromise { origin = origin.replace(/\/$/, '') if (!name || !origin) { throw new Error('Invalid Match Maker Origin Or Appilication Name') } const url = `${origin}/GetPixelStreamingInstance?ApplicationName=${name}` const response = await fetch(url) const data: PixelStreamingData = await response.json() // ... if (data.Code !== '0') { setTimeout(() => requestInstance(origin, name), 1000) } return data.Data } ``` ### Step 5 漏洞修复 经调试,data.Code 为 12 时 data.Data 为 null,逻辑需要调整。 ```ts if (!data.Data) { throw new Error('Get Pixel Streaming Instance Failed!') } // ... if (data.Code !== '0') { setTimeout(() => requestInstance(origin, name), 1000) } ``` - 检测 data.Code 为 12 的逻辑前置 - 计时器部分(延迟轮询)补充返回值 以上代码改为: ```ts if (data.Code === '1' || data.Code === '2') { return await requestInstanceLater(origin, name) } if (!data.Data) { throw new Error('Get Pixel Streaming Instance Failed!') } // ... function requestInstanceLater(origin: string, name: string) { return new Promise((resolve, reject) => { setTimeout(() => { requestInstance(origin, name).then(resolve).catch(reject) }, 1000) }) } ``` ### After ```ts type PixelStreamingCode = '0' | '1' | '2' | '3' interface PixelStreamingData { Code: PixelStreamingCode Data: string | null Result: string } export async function requestInstance(origin: string, name: string) { origin = origin.replace(/\/$/, '') if (!name || !origin) { throw new Error('Invalid Match Maker Origin Or Appilication Name') } const url = `${origin}/GetPixelStreamingInstance?ApplicationName=${name}` const response = await fetch(url) const data: PixelStreamingData = await response.json() if (data.Code === '1' || data.Code === '2') { return await requestInstanceLater(origin, name) } if (!data.Data) { throw new Error('Get Pixel Streaming Instance Failed!') } if (data.Code === '3') { throw new Error(data.Data) } return data.Data } export function requestInstanceLater(origin: string, name: string) { return new Promise((resolve: (value: string) => void) => { setTimeout(() => { requestInstance(origin, name).then(resolve) }, 1000) }) } ```