当前位置: 首页 > news >正文

TypeScript学习篇-类型介绍使用、ts相关面试题

文章目录

  • 基础知识
    • 基础类型: number, string, boolean, object, array, undefined, void(代表该函数没有返回值)
      • enum(枚举): 定义一个可枚举的对象
      • type
      • interface
      • 联合类型: |
      • 交叉类型: &
      • any 类型
      • null 和 undefined
        • null
        • undefined
      • never类型
    • 面试题及实战
      • 1. 你觉得使用ts的好处是什么?
      • 2. type 和 interface的异同
      • 3. 如何基于一个已有类型, 扩展出一个大部分内容相似, 但是有部分区别的类型?
      • 4. 什么是泛型, 泛型的具体使用?
      • 5. 写一个计算时间的装饰器
      • 6. 写一个缓存的装饰器
      • 7. 实现一个路由跳转 通过ts约束参数的routeHelper
      • 8. 实现一个基于ts和事件模式的countdown基础类
        • 使用
      • 9. npm install一个模块,都发生了什么
      • 10. eventemitter3

执行ts文件命令: tsc 文件.ts

基础知识

基础类型: number, string, boolean, object, array, undefined, void(代表该函数没有返回值)

类型关键字描述
任意类型any声明为 any 的变量可以赋予任意类型的值。
数字类型number双精度64位浮点值, 它可以用来表示整数和分数:
let num: number = 666;
字符串类型stringlet str: string = '呀哈哈';
布尔类型booleanlet flag: boolean = true;
数组类型声明变量为数组
在元素类型后面加[]: let arr: number[] = [1,2];,
或使用数组泛行: let arr:Array<number> = [1,2];
元组元组类型用来表示已知元素数量和类型的数组, 各元素的类型不必相同, 对应位置的类型需要相同:
let x:[string,number];
正确: x = ['呀哈哈', 2];
错误: x = [2, '呀哈哈'];
枚举enum枚举类型用于定义数值集合
enum Color {Red, Green, Blue};
let c : Color = Color.Blue;
console.log(c); // 2
voidvoid用于标识方法返回值的类型, 表示该方法没有返回值
function hello(): void{ alert('Hello World'); }
nullnull表示对象值缺失
undefinedundefined用于初始化变量为一个未定义的值
nevernevernever是其他类型(包括 null 和 undefined) 的子类型, 代表从不会出现的值.

enum(枚举): 定义一个可枚举的对象

const obj = {'RUN':'run','EAT':'eat'
}
enum Obj {'RUN',// 默认 RUN = 0'EAT', // 默认 EAT = 1'ABC' = 'abc', // 使用 '=' 复制
}
// 使用
const eat = Obj.EAT;const getValue = () => {return 0
}enum List {A = getValue(),B = 2,  // 此处必须要初始化值,不然编译不通过C
}
console.log(List.A) // 0
console.log(List.B) // 2
console.log(List.C) // 3

type

type Action = 'eat'  | 'run';
// 声明 a 变量类型为 Action, 可选值为:'eat', 'run'
const a:Action = 'eat';

interface

interface data {name: string,age: number
};
const b: data = {name: 'yhh',age: 10
}
// 定义axios.post 返回值类型
axios.post<data>().then();

联合类型: |

交叉类型: &

any 类型

任意值是 typescript 针对编程时类型不明确的变量使用的一种数据类型. 常用于以下三种情况

// 变量的值会动态改变时, 比如来着用户的输入, 任意值类型可以让这些变量跳过编译阶段的类型检查
let x: any = 1;
x = 'yhh';
x = false;// 改写现有代码时, 任意值允许在编译时可选择地包含或移除类型检查
let x: any = 4;
x.isEmpty(); // 正确, isEmpty方法在运行时可能存在, 但这里并不会检查
x.toFixed(); // 正确// 定义存储各种类型数据的数组时
ler arrayList: any[] = [1,false,'fine'];
arratList[1] = 100;

null 和 undefined

null

nullJavaScript 中 表示’什么都没有’.

null 是一个只有一个值的特殊类型, 表示一个空对象引用.

typeof 检测 null 返回是 object.

undefined

undefinedjavascript 中是一个没有设置值的变量.

typeof 一个没有值的变量会返回 undefined.

NullUndefined 是其他任何类型(包括void)的子类型. 可以赋值给其他类型, 比如数字类型, 赋值后的类型会变成 nullundefined.

typescript 中启用严格的空检验(--strictnullChecks)特性, 就可以使 nullundefined 只能被赋值给 void 或本身对应的类型.

// 启用 --strictnullChecks 
let x : number;
x = 1;
x = undefined; // 错误, 因为 x 只能是数字类型
x = null; // 错误// 如果一个类型可能出现 null 或 undefined, 可以使用 | 类支持多中类型
// 启用 --strictnullChecks 
let x : number | null | undefined;
x = 1;
x = undefined; // 正确
x = null; // 正确

never类型

never 是其他类型(包括nullundefined)的子类型, 代表从不会出现的值. 这意味着声明never类型的变量只能被never类型所赋值, 在函数中通常表现为抛出异常或无法执行到终止点.

let x : never;
let y : number;x = 123; // 错误, 数字类型不可转为 never 类型// 正确, never 类型可以赋值给 never类型
x = (()=>{ throw new Error('exception') })();
// 正确, never 类型可以赋值给 数字类型
y = (()=>{ throw new Error('exception') })();// 返回值为 never 的函数可以是抛出异常的情况
function error(message:string): never{throw new Error(message);
}
// 返回值为 never 的函数可以是无法被执行到终止点的情况
function loop(): never{while (true){}
}

面试题及实战

1. 你觉得使用ts的好处是什么?

1.1 TypeScript是JavaScript的加强版,它给JavaScript添加了可选的静态类型和基于类的面向对象编程,它拓展了JavaScript的语法。所以ts的功能比js只多不少.
1.2 Typescript 是纯面向对象的编程语言,包含类和接口的概念.
1.3 TS 在开发时就能给出编译错误, 而 JS 错误则需要在运行时才能暴露。
1.4 作为强类型语言,你可以明确知道数据的类型。代码可读性极强,几乎每个人都能理解。
1.5 ts中有很多很方便的特性, 比如可选链.

2. type 和 interface的异同

重点:用interface描述数据结构,用type描述类型

2.1 都可以描述一个对象或者函数

interface User {name: stringage: number
}interface SetUser {(name: string, age: number): void;
}type User = {name: stringage: number
};type SetUser = (name: string, age: number)=> void;

2.2 都允许拓展(extends)
interface 和 type 都可以拓展,并且两者并不是相互独立的,也就是说 interface 可以 extends type, type 也可以 extends interface 。 虽然效果差不多,但是两者语法不同。

// interface extends interface
interface Name { name: string; 
}
interface User extends Name { age: number; 
}// type extends type
type Name = { name: string; 
}
type User = Name & { age: number  };// interface extends type
type Name = { name: string; 
}
interface User extends Name { age: number; 
}// type extends interface
interface Name { name: string; 
}
type User = Name & { age: number; 
}

2.3 只有type可以做的

type 可以声明基本类型别名,联合类型,元组等类型

// 基本类型别名
type Name = string// 联合类型
interface Dog {wong();
}
interface Cat {miao();
}type Pet = Dog | Cat// 具体定义数组每个位置的类型
type PetList = [Dog, Pet]// 当你想获取一个变量的类型时,使用 typeof
let div = document.createElement('div');
type B = typeof div

3. 如何基于一个已有类型, 扩展出一个大部分内容相似, 但是有部分区别的类型?

首先可以通过Pick和Omit

interface Test {name: string;sex: number;height: string;
}type Sex = Pick<Test, 'sex'>;const a: Sex = { sex: 1 };type WithoutSex = Omit<Test, 'sex'>;const b: WithoutSex = { name: '1111', height: 'sss' };

比如Partial, Required.

再者可以通过泛型.

4. 什么是泛型, 泛型的具体使用?

泛型是指在定义函数、接口或类的时候,不预先指定具体的类型,使用时再去指定类型的一种特性。

可以把泛型理解为代表类型的参数

interface Test<T = any> {userId: T;
}type TestA = Test<string>;
type TestB = Test<number>;const a: TestA = {userId: '111',
};const b: TestB = {userId: 2222,
};

5. 写一个计算时间的装饰器

export function before(beforeFn: any) {return function(target: any, name: any, descriptor: any) {const oldValue = descriptor.value;descriptor.value = function() {beforeFn.apply(this, arguments);return oldValue.apply(this, arguments);};return descriptor;};
}export function after(afterFn: any) {return function(target: any, name: any, descriptor: any) {const oldValue = descriptor.value;descriptor.value = function() {const ret = oldValue.apply(this, arguments);afterFn.apply(this, arguments);return ret;};return descriptor;};
}
// 计算时间
export function measure(target: any, name: any, descriptor: any) {const oldValue = descriptor.value;descriptor.value = async function() {const start = Date.now();const ret = await oldValue.apply(this, arguments);console.log(`${name}执行耗时 ${Date.now() - start}ms`);return ret;};return descriptor;
}

6. 写一个缓存的装饰器

const cacheMap = new Map();export function EnableCache(target: any, name: string, descriptor: PropertyDescriptor) {const val = descriptor.value;descriptor.value = async function(...args: any) {const cacheKey = name + JSON.stringify(args);if (!cacheMap.get(cacheKey)) {const cacheValue = Promise.resolve(val.apply(this, args)).catch((_) => cacheMap.set(cacheKey, null));cacheMap.set(cacheKey, cacheValue);}return cacheMap.get(cacheKey);};return descriptor;
}

7. 实现一个路由跳转 通过ts约束参数的routeHelper

import { Dictionary } from 'vue-router/types/router';
import Router, { RoutePath } from '../router';export type BaseRouteType = Dictionary<string>;export interface IndexParam extends BaseRouteType {name: string;
}export interface AboutPageParam extends BaseRouteType {testName: string;
}export interface UserPageParam extends BaseRouteType {userId: string;
}export interface ParamsMap {[RoutePath.Index]: IndexParam;[RoutePath.About]: AboutPageParam;[RoutePath.User]: UserPageParam;
}export class RouterHelper {public static replace<T extends RoutePath>(routePath: T, params: ParamsMap[T]) {Router.replace({path: routePath,query: params,});}public static push<T extends RoutePath>(routePath: T, params: ParamsMap[T]) {Router.push({path: routePath,query: params,});}
}

8. 实现一个基于ts和事件模式的countdown基础类

import { EventEmitter } from 'eventemitter3';export interface RemainTimeData {/** 天数 */days: number;/*** 小时数*/hours: number;/*** 分钟数*/minutes: number;/*** 秒数*/seconds: number;/*** 毫秒数*/count: number;
}export type CountdownCallback = (remainTimeData: RemainTimeData, remainTime: number) => void;enum CountdownStatus {running,paused,stoped,
}
// 练习
interface User {name: stringage: number
}
function test<T extends User>(params: T): T{return params
}
test({name:'1',age:1});export enum CountdownEventName {START = 'start',STOP = 'stop',RUNNING = 'running',
}
interface CountdownEventMap {[CountdownEventName.START]: [];[CountdownEventName.STOP]: [];[CountdownEventName.RUNNING]: [RemainTimeData, number];
}export function fillZero(num: number) {return `0${num}`.slice(-2);
}export class Countdown extends EventEmitter<CountdownEventMap> {private static COUNT_IN_MILLISECOND: number = 1 * 100;private static SECOND_IN_MILLISECOND: number = 10 * Countdown.COUNT_IN_MILLISECOND;private static MINUTE_IN_MILLISECOND: number = 60 * Countdown.SECOND_IN_MILLISECOND;private static HOUR_IN_MILLISECOND: number = 60 * Countdown.MINUTE_IN_MILLISECOND;private static DAY_IN_MILLISECOND: number = 24 * Countdown.HOUR_IN_MILLISECOND;private endTime: number;private remainTime: number = 0;private status: CountdownStatus = CountdownStatus.stoped;private step: number;constructor(endTime: number, step: number = 1e3) {super();this.endTime = endTime;this.step = step;this.start();}public start() {this.emit(CountdownEventName.START);this.status = CountdownStatus.running;this.countdown();}public stop() {this.emit(CountdownEventName.STOP);this.status = CountdownStatus.stoped;}private countdown() {if (this.status !== CountdownStatus.running) {return;}this.remainTime = Math.max(this.endTime - Date.now(), 0);this.emit(CountdownEventName.RUNNING, this.parseRemainTime(this.remainTime), this.remainTime);if (this.remainTime > 0) {setTimeout(() => this.countdown(), this.step);} else {this.stop();}}private parseRemainTime(remainTime: number): RemainTimeData {let time = remainTime;const days = Math.floor(time / Countdown.DAY_IN_MILLISECOND);time = time % Countdown.DAY_IN_MILLISECOND;const hours = Math.floor(time / Countdown.HOUR_IN_MILLISECOND);time = time % Countdown.HOUR_IN_MILLISECOND;const minutes = Math.floor(time / Countdown.MINUTE_IN_MILLISECOND);time = time % Countdown.MINUTE_IN_MILLISECOND;const seconds = Math.floor(time / Countdown.SECOND_IN_MILLISECOND);time = time % Countdown.SECOND_IN_MILLISECOND;const count = Math.floor(time / Countdown.COUNT_IN_MILLISECOND);return {days,hours,minutes,seconds,count,};}
}
使用
<template><div class="home" @click="toAboutPage"><img alt="Vue logo" src="../assets/logo.png"><HelloWorld msg="Welcome to Your Vue.js + TypeScript App"/><div>倒计时:{{timeDisplay}}</div></div>
</template><script lang="ts">
import { Component, Vue } from 'vue-property-decorator';
import HelloWorld from '../components/HelloWorld.vue';
import { RouterHelper } from '../lib/routerHelper';
import { Countdown, CountdownEventName, fillZero } from '../lib/countdown';
import { RoutePath } from '../router';
import { measure } from '../decorator';@Component({components: {HelloWorld,},
})
export default class Home extends Vue {public timeDisplay: string = '';@measurepublic toAboutPage() {RouterHelper.push(RoutePath.About, {  testName: '1111' });}public created() {const countdown = new Countdown(Date.now() + 60 * 60 * 1000, 10);countdown.on(CountdownEventName.RUNNING, (remainTimeData) => {const { hours, minutes, seconds, count} = remainTimeData;this.timeDisplay = [hours, minutes, seconds, count].map(fillZero).join(':');});}
}
</script>

9. npm install一个模块,都发生了什么

npm install命令输入 > 检查node_modules目录下是否存在指定的依赖 > 如果已经存在则不必重新安装 > 若不存在,继续下面的步骤 > 向 registry(本地电脑的.npmrc文件里有对应的配置地址)查询模块压缩包的网址 > 下载压缩包,存放到根目录里的.npm目录里 > 解压压缩包到当前项目的node_modules目录中。

10. eventemitter3

相关文章:

TypeScript学习篇-类型介绍使用、ts相关面试题

文章目录 基础知识基础类型: number, string, boolean, object, array, undefined, void(代表该函数没有返回值)enum(枚举): 定义一个可枚举的对象typeinterface联合类型: |交叉类型: &any 类型null 和 undefinednullundefined never类型 面试题及实战1. 你觉得使用ts的好处…...

超详细!Jmeter性能测试

前言 性能测试是一个全栈工程师/架构师必会的技能之一&#xff0c;只有学会性能测试&#xff0c;才能根据得到的测试报告进行分析&#xff0c;找到系统性能的瓶颈所在&#xff0c;而这也是优化架构设计中重要的依据。 测试流程&#xff1a; 需求分析→环境搭建→测试计划→脚…...

C语言经典习题24

文件操作习题 一 编程删除从C盘home文件夹下data.txt文本文件中所读取字符串中指定的字符&#xff0c;该指定字符由键盘输入&#xff0c;并将修改后的字符串以追加方式写入到文本文件C:\home\data.txt中。 #include<stdio.h> main() { char s[100],ch; int i;…...

SQL labs-SQL注入(三,sqlmap使用)

本文仅作为学习参考使用&#xff0c;本文作者对任何使用本文进行渗透攻击破坏不负任何责任。 引言&#xff1a; 盲注简述&#xff1a;是在没有回显得情况下采用的注入方式&#xff0c;分为布尔盲注和时间盲注。 布尔盲注&#xff1a;布尔仅有两种形式&#xff0c;ture&#…...

统一认证与单点登录:简明概述与应用

1. 统一认证概述 统一认证是一种身份验证机制&#xff0c;允许用户使用一个账户来访问多个系统和应用程序。它的主要目标是简化用户的登录过程&#xff0c;提高安全性&#xff0c;并减少管理开销。统一认证通过集中管理用户信息&#xff0c;使得用户只需一次认证即可访问不同的…...

MSPM0G3507学习笔记1:开发环境_引脚认识与点灯

今日速通一款Ti的单片机用于电赛&#xff1a;MSPM0G3507 这里默认已经安装好了Keil5_MDK 首先声明一下: 因为是速成&#xff0c;所以需要一定单片机学习基础&#xff0c;然后我写的也不会详细&#xff0c;这个专栏的笔记也就是自己能看懂就行的目标~~~ 文章提供测试代码解…...

使用法国云手机进行面向法国的社媒营销

在当今数字化和全球化的时代&#xff0c;社交媒体已经成为企业营销和拓展市场的重要工具。对于想进入法国市场的企业来说&#xff0c;如何在海外社媒营销中脱颖而出、抓住更多的市场份额&#xff0c;成为了一个关键问题。法国云手机正为企业提供全新的营销工具&#xff0c;助力…...

C++学习笔记——模板

学习视频 文章目录 模板的概念函数模板函数模板语法函数模板注意事项函数模板案例普通函数与函数模板的区别普通函数与函数模板的调用规则模板的局限性 类模板类模板与函数模板区别类模板中成员函数创建时机类模板对象做函数参数类模板与继承类模板成员函数类外实现类模板分文件…...

财务分析,奥威BI行计算助力财务解放报表工作

【财务分析&#xff0c;奥威BI行计算助力财务解放报表工作】 在企业的财务管理体系中&#xff0c;财务报表的编制与分析是至关重要的一环。然而&#xff0c;传统的手工编制报表方式不仅耗时耗力&#xff0c;还难以应对日益复杂多变的财务数据需求。奥威BI&#xff08;Business…...

文件写入、读出-linux

基于linux操作系统&#xff0c;编写存储功能&#xff0c;在网上搜了几个例子&#xff0c;一直报创建错误&#xff0c; fopen(SAVE_PATH_OWN_INF_FILE, "w") fopen(SAVE_PATH_OWN_INF_FILE, "a"), 使用这两个创建均失败&#xff0c;最后发现创建可以用以…...

环境搭建-Windows系统搭建Docker

Windows系统搭建Docker 一、系统虚拟化1.1 启用虚拟化2.2 启用Hyper-v并开启虚拟任务 三、安装WSL3.1 检验安装3.2 安装WSL 四、Docker安装4.1 Docker安装包下载4.2 Docker安装4.3 运行docker Desktop 五、Docker配置5.1 打开Docker配置中心5.2 配置Docker国内镜像 六、使用 一…...

k8s零零散散问题

安装教程 https://blog.csdn.net/weixin_43933728/article/details/137977799 加入集群错误问题 https://blog.csdn.net/Linbling/article/details/139122862...

The Llama 3 Herd of Models.Llama 3 模型论文全文

现代人工智能(AI)系统是由基础模型驱动的。本文提出了一套新的基础模型,称为Llama 3。它是一组语言模型,支持多语言、编码、推理和工具使用。我们最大的模型是一个密集的Transformer,具有405B个参数和多达128K个tokens的上下文窗口。本文对Llama 3进行了广泛的实证评价。我们…...

ChatGPT的原理和成本

ChatGPT就是人机交互的一个底层系统&#xff0c;某种程度上可以类比于操作系统。在这个操作系统上&#xff0c;人与AI之间的交互用的是人的语言&#xff0c;不再是冷冰冰的机器语言&#xff0c;或者高级机器语言&#xff0c;当然&#xff0c;在未来的十来年内&#xff0c;机器语…...

无刷电机的ESC电子速度控制模块夹紧铁芯或更换镇流器

△u/s中后一项经过二极管半波整流、电容C1滤波后,使原有的脉动电压曲线Us上再0.45ys的波形如叠加一个直流电压,其大小为-Lu,即为△U当压差△U太大,使0.45△U≥Ucz时,电容C1两端电压uc不可能降至下信号。所以该电路同样可以检测出压差压差较小时才能发出合闸脉冲。 压差△U的检…...

OpenAI发布AI搜索惨遭翻车?新老搜索的较量愈演愈烈!

引言 在信息爆炸的时代&#xff0c;每一次技术的飞跃都如同海平面上跃起的鲸鱼&#xff0c;既震撼人心&#xff0c;也搅动着深海的宁静。近日&#xff0c;科技巨头OpenAI发布的AI搜索功能&#xff0c;本欲以智能之名重塑搜索领域的版图&#xff0c;却不料遭遇了市场的“暗礁”…...

SpringBoot整合阿里云短信业务

详细介绍SpringBoot整合阿里云短信服务的每一步过程&#xff0c;同时会将验证码存放到Redis中并设置过期时间&#xff0c;尽量保证实战的同时也让没做过的好兄弟也能实现发短信的功能~ 1. 注册阿里云账号和创建Access Key 首先&#xff0c;你需要注册一个阿里云账号&#xff0…...

Kubernetes安全--securityContext介绍

作者&#xff1a;雅泽 securityContext是用来控制容器内的用户权限&#xff0c;你想用什么用户去执行程序或者执行操作等等。 1. securityContext介绍 安全上下文&#xff08;Security Context&#xff09;定义 Pod 或 Container 的特权与访问控制设置。 安全上下文包括但不…...

【React】通过实际示例详解评论列表渲染和删除

文章目录 一、引言二、初始状态与状态更新1. 使用useState钩子管理状态2. 评论列表的初始数据 三、列表渲染的实现1. list.map(item > { ... })2. return 语句3. JSX 语法4. 为什么这样设计5. 完整解读 四、列表项的唯一标识1. key 的作用2. key 的用法3. 可以没有 key 吗&a…...

React 中 useState 语法详解

1. 语法定义 const [state, dispatch] useState(initData) state&#xff1a;定义的数据源&#xff0c;可视作一个函数组件内部的变量&#xff0c;但只在首次渲染被创造。 dispatch&#xff1a;改变state的函数&#xff0c;推动函数渲染的渲染函数&#xff0c;有非函数和函…...

如何为服务器生成TLS证书

TLS&#xff08;Transport Layer Security&#xff09;证书是确保网络通信安全的重要手段&#xff0c;它通过加密技术保护传输的数据不被窃听和篡改。在服务器上配置TLS证书&#xff0c;可以使用户通过HTTPS协议安全地访问您的网站。本文将详细介绍如何在服务器上生成一个TLS证…...

【HarmonyOS 5 开发速记】如何获取用户信息(头像/昵称/手机号)

1.获取 authorizationCode&#xff1a; 2.利用 authorizationCode 获取 accessToken&#xff1a;文档中心 3.获取手机&#xff1a;文档中心 4.获取昵称头像&#xff1a;文档中心 首先创建 request 若要获取手机号&#xff0c;scope必填 phone&#xff0c;permissions 必填 …...

AI书签管理工具开发全记录(十九):嵌入资源处理

1.前言 &#x1f4dd; 在上一篇文章中&#xff0c;我们完成了书签的导入导出功能。本篇文章我们研究如何处理嵌入资源&#xff0c;方便后续将资源打包到一个可执行文件中。 2.embed介绍 &#x1f3af; Go 1.16 引入了革命性的 embed 包&#xff0c;彻底改变了静态资源管理的…...

Mac下Android Studio扫描根目录卡死问题记录

环境信息 操作系统: macOS 15.5 (Apple M2芯片)Android Studio版本: Meerkat Feature Drop | 2024.3.2 Patch 1 (Build #AI-243.26053.27.2432.13536105, 2025年5月22日构建) 问题现象 在项目开发过程中&#xff0c;提示一个依赖外部头文件的cpp源文件需要同步&#xff0c;点…...

DBLP数据库是什么?

DBLP&#xff08;Digital Bibliography & Library Project&#xff09;Computer Science Bibliography是全球著名的计算机科学出版物的开放书目数据库。DBLP所收录的期刊和会议论文质量较高&#xff0c;数据库文献更新速度很快&#xff0c;很好地反映了国际计算机科学学术研…...

Mac flutter环境搭建

一、下载flutter sdk 制作 Android 应用 | Flutter 中文文档 - Flutter 中文开发者网站 - Flutter 1、查看mac电脑处理器选择sdk 2、解压 unzip ~/Downloads/flutter_macos_arm64_3.32.2-stable.zip \ -d ~/development/ 3、添加环境变量 命令行打开配置环境变量文件 ope…...

goreplay

1.github地址 https://github.com/buger/goreplay 2.简单介绍 GoReplay 是一个开源的网络监控工具&#xff0c;可以记录用户的实时流量并将其用于镜像、负载测试、监控和详细分析。 3.出现背景 随着应用程序的增长&#xff0c;测试它所需的工作量也会呈指数级增长。GoRepl…...

spring boot使用HttpServletResponse实现sse后端流式输出消息

1.以前只是看过SSE的相关文章&#xff0c;没有具体实践&#xff0c;这次接入AI大模型使用到了流式输出&#xff0c;涉及到给前端流式返回&#xff0c;所以记录一下。 2.resp要设置为text/event-stream resp.setContentType("text/event-stream"); resp.setCharacter…...

[10-1]I2C通信协议 江协科技学习笔记(17个知识点)

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17...

无头浏览器技术:Python爬虫如何精准模拟搜索点击

1. 无头浏览器技术概述 1.1 什么是无头浏览器&#xff1f; 无头浏览器是一种没有图形用户界面&#xff08;GUI&#xff09;的浏览器&#xff0c;它通过程序控制浏览器内核&#xff08;如Chromium、Firefox&#xff09;执行页面加载、JavaScript渲染、表单提交等操作。由于不渲…...