当前位置: 首页 > 知识库问答 >
问题:

javascript - 后端接口返回的时间 和 axios 从 request 到 response 过程的时间 相差巨大?

凌昕
2023-11-24

后端接口返回的时间 和 axios 从 request 到 response 过程的时间 相差巨大?

背景
在用扫码枪扫货品的时候会调接口 每扫一个货品需要请求三个不同接口 在扫前40个货品的时候时间相差不大, 但是一直扫到150+货品的时候 就会出现 时间相差很大的情况


 

图一是接口返回的时间180ms 图三 从axios request 到 response 前 变成了 800ms
图四 在组件内发起请求到数据返回 时间变成了差不多1800ms 中间没做数据操作 只有增加了请求拦截和响应错误码处理 中间的时间相差这么多 是什么问题导致呢?

// import axios from 'axios'import axios, { AxiosRequestConfig, AxiosResponse, CancelTokenSource } from 'axios';import baseUrl, { differUrl } from './baseUrl';import router from '@/router';import store from '@/store';import { Message } from 'element-ui';import { vMessage } from '@rbp/components/base-message';import { filedMapData, moduleIdMapData } from './config';import { hideScreenLoading, showScreenLoading } from '@/utils/loading';import { getCookie, getToken, removeCookie } from '@/utils/auth';let configChace: any = null; // 存放请求参数,在进入错误时候也关掉loadingconst CANCELTTYPE = {    CACHE: 1,    REPEAT: 2};interface Request {    onlyKey: string;    url: string;    source: CancelTokenSource;}const pendingRequests: Request[] = [];const config = {    // timeout: 1000 * 60 * 10    // baseURL: baseUrl};// eslint-disable-next-line no-unused-varsconst _axios = axios.create(config);const DELAY = 0;let timer: any, loadingInstance: any;const setBaseUrl = (config) => {    const initUrl = config.url;    if (initUrl && initUrl.startsWith('/customize')) {        config.baseURL = differUrl || baseUrl;        config.baseURL = config.baseURL.replace('/manager', '');        config.timeout = 1000 * 60 * 10;    } else if (initUrl && initUrl.startsWith('/report')) {        config.baseURL = (Window as any).config.reportUrl || baseUrl;        config.timeout = 1000 * 60 * 10;    } else if (initUrl && initUrl.startsWith('/new-mf-fac')) {        config.baseURL = localStorage.getItem('JuNiu_WebAddress') || baseUrl;        config.timeout = 1000 * 60 * 10;    } else {        config.baseURL = baseUrl;        config.timeout = 1000 * 60 * 3;    }};const setToken = (config) => {    const token = getToken();    const refreshToken = getCookie('refreshToken');    config.headers.Lang = getCookie('language') || 'zh_chs';    if (token) {        config.headers['Authorization'] = token; // 让每个请求携带自定义token 请根据实际情况自行修改    }    if (refreshToken) {        config.headers['RefreshToken'] = refreshToken;    }};const setModuleId = (config) => {    const formatRouter: any = (window as any).__POWERED_BY_QIANKUN__ ? (window as any).ymyCustomizeRouter : router;    // 模块 ID 参数 全局传入    // const moduleId = (router as any).history.current.meta.moduleId;    // let moduleId =    //     (window as any).Vue2 && (window as any).Vue2.prototype    //         ? (window as any).Vue2.prototype._router_.history.current.meta.moduleId    //         : (router as any).history.current.meta.moduleId;    let moduleId =        (window as any).Vue2 && (window as any).Vue2.prototype            ? (window as any).Vue2.prototype._router_.history.current.meta.moduleId            : formatRouter.history.current.meta.moduleId;    // 对于非/customize接口,替换moduleId为新moduleId    if (config?.url.indexOf('/customize') < 0 && config?.url.indexOf('/role/authority') < 0) {        const obj = moduleIdMapData(config.url, moduleId) || filedMapData(config.url, moduleId);        if (obj?.moduleId) {            config.url = obj.url;            moduleId = obj.moduleId;            if (config.params) {                Object.keys(config.params).forEach((key) => {                    if (['baseModuleId', 'moduleId'].includes(key)) {                        config.params[key] = obj.moduleId;                    }                });            }        }    }    // if (moduleId && config.data) {    // if (config.data && config.data.moduleId) {    //     Object.assign(config.data, { moduleId: config.data.moduleId });    // }    if (moduleId && config.data) {        // NetNeedModuleId 接口不需要 moduleId 为 true 则不需要加        if (config.data.NetNeedModuleId) {            delete config.data.NetNeedModuleId;        } else {            if (Object.keys(config.data).indexOf('moduleId') > -1) {                moduleId = config.data.moduleId;            }            Object.assign(config.data, { moduleId: moduleId });            if (typeof config.data.data === 'object') {                if (config?.url.indexOf('/customize') < 0) {                    // 对于非/customize接口,将参数中moduleId替换为新moduleId                    if (Object.keys(config.data.data).indexOf('moduleId') > -1) {                        config.data.data.moduleId = moduleId;                    }                } else {                    if (Object.keys(config.data.data).indexOf('moduleId') > -1 && config.data.data.moduleId) {                        moduleId = config.data.data.moduleId;                    }                }                Object.assign(config.data.data, { moduleId: moduleId });            }        }        if (config.data.setModuleIdInHeaders) {            config.headers['moduleId'] = moduleId;            delete config.data.setModuleIdInHeaders;        }    }};const setLoading = (config) => {    configChace = config;    // NetNeedModuleId 接口不需要 moduleId 为 true 则不需要加    if (config.method === 'get' && (!config.params || !config.params.NetNeedLoading)) {        config.headers['showLoading'] = true;        showScreenLoading(config.headers);    } else if (['put', 'post'].includes(config.method) && (!config.data || !config.data.NetNeedLoading)) {        config.headers['showLoading'] = true;        showScreenLoading(config.headers);    }    config.params && delete config.params.NetNeedLoading;    config.data && delete config.data.NetNeedLoading;};const preventSomeRequest = (config) => {    /**     * 为每一次请求生成一个cancleToken     */    const source = axios.CancelToken.source();    config.cancelToken = source.token;    /**     * 将之前的重复且未完成的请求全部取消     */    const params = JSON.stringify(config.params || config.data);    const hits = pendingRequests.filter((item) => item.onlyKey === `${config.baseURL}${config.url}${params}`);    if (hits.length > 0) {        console.error('有重复请求', hits, config);        hits.forEach((item) => item.source.cancel(CANCELTTYPE.REPEAT.toString()));    }    pendingRequests.push({        onlyKey: `${config.baseURL}${config.url}${params}`,        url: `${config.baseURL}${config.url!}`,        source    });};_axios.interceptors.request.use(    function (config: AxiosRequestConfig) {        // 全局请求的 loading,当请求 100 ms 后还没返回,才会出现 loading        console.time('_axios.interceptors.request 请求设置header等等信息');        console.time('请求整理到返回中途所需要时间');        config.headers['request-startTime'] = new Date().getTime();        setBaseUrl(config);        setToken(config);        setModuleId(config);        setLoading(config);        // preventSomeRequest(config);        console.timeEnd('_axios.interceptors.request 请求设置header等等信息');        return config;    },    function (error) {        // clearTimeout(timer);        // if (loadingInstance) loadingInstance.close();        // if (config!.headers.showLoading) {        if (configChace.headers['showLoading']) {            hideScreenLoading();            configChace = null;        }        // }        return Promise.reject(error);    });// Add a response interceptor_axios.interceptors.response.use(    function (response: AxiosResponse) {        // clearTimeout(timer);        // if (loadingInstance) loadingInstance.close();        const headers = response.config.headers;        headers && headers.showLoading && hideScreenLoading();        /**         * code为非20000是抛错 可结合自己业务进行修改         */        /**         * 不论请求是否成功,         * 将本次完成的请求从请求队列中移除         */        // 以同样的加密方式(MD5)获取加密字符串        const index = pendingRequests.findIndex((item) => item.url === response.config.url);        //        if (index > -1) {            pendingRequests.splice(index, 1);        }        if (response.config.responseType === 'blob') {            return response.data;        }        const res = response.data;        const FIXCODE = [            0,            10008,            10107,            10112,            10111,            10010,            20001,            30001,            30102,            30103,            30105,            30106,            40100,            40110,            40120,            40121,            40130,            40131,            40140,            40141,            40142,            40160,            40161,            40170,            40180,            50006,            50008,            50009,            50011,            50013,            50014,            50015,            50016,            50017,            50018,            50019,            50020,            50021,            50022,            50024,            50028, // 联营结算模式审核异常code码            50029,            50030,            50025, // 成本结存异常码(未做库存结存的渠道)            50031, // 成本结存异常码(存在以下未审核单据)            50032, // 成本结存异常码(存在本期数量未负的货品)            50033        ];        const NO_TOKEN_CODE = [10006]; // 没有权限或者和token失效        const PROGRAM_ERROR_CODE = [500, 10001, 10002]; // 显示错误具体信息弹窗 带复制等功能        console.timeEnd('请求整理到返回中途所需要时间');        if (PROGRAM_ERROR_CODE.includes(res.code)) {            // Infrom({ type: 'error', content: res.msg, detail: res.errorStack, confirmButtonText: '关闭' });            Message({                type: 'error',                message: res.msg,                duration: 3500            });            return Promise.reject('error');        } else if (FIXCODE.includes(res.code)) {            const start = response.config.headers['request-startTime'];            const currentTime = new Date().getTime();            const requestDuration = ((currentTime - start) / 1000).toFixed(2) + 's';            console.log(`%caxios.ts line:288 ${response.config.url} 接口花费时间`, 'requestDuration', requestDuration);            // return res;            return Promise.resolve(res);        } else if (NO_TOKEN_CODE.includes(res.code)) {            //接口登陆失效跳转登录页            vMessage({                type: 'error',                message: res.msg || res.errorStack,                showClose: true,                duration: 3500            });            removeCookie('tempToken');            removeCookie('tempRefreshToken');            store.dispatch('user/resetToken').then(() => {                setTimeout(() => {                    window.location.reload();                }, 500);            });            return Promise.reject('loginError');        } else {            Message({                type: 'error',                message: res.msg || res.errorStack,                duration: 3500            });            return Promise.reject('error');        }    },    function (error) {        // clearTimeout(timer);        // if (loadingInstance) loadingInstance.close();        // if (response.config.headers.showLoading) {        // }        // setTimeout(() => {        //     hideScreenLoading();        // }, 200);        // 这里是重复请求不弹出        if (error.message !== CANCELTTYPE.REPEAT.toString()) {            if (configChace.headers['showLoading']) {                hideScreenLoading();                configChace = null;            }            // Infrom({ type: 'error', content: error.msg || '请求超时或服务器异常,请检查网络或联系管理员' });            Message({                type: 'error',                message: error.msg || '请求超时或服务器异常,请检查网络或联系管理员'            });        }        return Promise.reject(error);    });export default _axios;

共有2个答案

咸晨
2023-11-24

这段时间涵盖的处理过程太多,尤其是网络过程非常不稳定。要先确定是哪部分造成报时间的大辐增加,如果是网络造成的,那前端不太可能做优化。

如果是想做纯粹的前端监测,从前端可以监测的点开始计时到当前处理不能监测时结束。比如你猜测是拦截引起的效率问题,那你可以只监测这部分处理所花的时间来确认是否是这个问题。

长孙鸿波
2023-11-24

主要看图一的数据,延迟应该是服务端导致的吧,再延迟出现的时候,api的耗时是多少,请截图一的数据,分析一下

 类似资料:
  • 问题内容: 假设我有一个时间戳值的DataFrame : 我想创建一个新列。我可以通过编写一个简短的函数并使用它来迭代地创建它来创建它: 然后,我将看到以下结果: 什么我 想 实现的是这样一些较短的转变(我知道是错误的,但在精神得到): 显然,该列是类型的,因此没有这些属性,但是似乎有一种使用矩阵运算的简单方法。 有更直接的方法吗? 问题答案: 假设时间戳是数据帧的索引,则可以执行以下操作: 如果

  • 我以为问题首先是与Postgres有关,但后来我发现不是。当我检查终端时,显示的是正确的日期。又名2021-04-15。但是,当我使用相同的查询将其返回到我的前端时,日期和时间是错误的。(终端中没有时间戳,但返回结果前端中有一个。这是我返回前端的代码。 我的前端代码如下。 我的前端正在以以下格式返回数据-2021-04-14T23:00:00.000Z。它目前是英国的第15届,它(在撰写本报告时)

  • 问题内容: 我知道我可以使用momentjs做任何事情,还可以做一些涉及日期的事情。但是令人尴尬的是,我很难去做一件看起来很简单的事情:得到两次之间的差。 例: 我试过的 我不知道那里的“ 10”是什么。我住在巴西,所以如果相关的话,我们是utc-0300。 结果是持续时间正确的内部值: 所以,我想我的问题是:如何将momentjs持续时间转换为时间间隔?我肯定可以用 但我觉得有一些更 优雅 ,我

  • 当我想分析 Laravel 是如何做到从 Request -> Response 的解析过程的,发现 Lumen 相对简单,所以今天从 Lumen 源代码入手,说一说Request -> Response 的解析过程 载入 Router 我们使用 Lumen 项目时,都是通过创建 route,将请求的方法 method、路径 uri 和执行 action关联在一起,用于解析 Request。 如:

  • 文档有点混乱。如果超时,该方法将返回什么?文件上写着“计算结果”,但如果计算超时怎么办?它是空的吗? 谢谢

  • 我创建并持久化一个df1,然后在其上执行以下操作: 我有一个有16个节点的集群(每个节点有1个worker和1个executor,4个内核和24GB Ram)和一个master(有15GB Ram)。Spark.shuffle.Partitions也是192个。它挂了2个小时,什么也没发生。Spark UI中没有任何活动。为什么挂这么久?是dagscheduler吗?我怎么查?如果你需要更多的信息