feat: 流式加载器 & fix: gl2 注释

This commit is contained in:
unanmed 2025-01-13 16:38:28 +08:00
parent 6dde0334e1
commit 231a72e78c
3 changed files with 94 additions and 2 deletions

View File

@ -1531,7 +1531,7 @@ export class GL2Program extends EventEmitter<ShaderProgramEvent> {
/**
* 定义一个 attribute 常量,并存入本着色器程序的 attribute 常量映射,在 es 300 版本中叫做 in
* @param attrib attribute 常量名
* @param type attribute 类型,可选 {@link Shader.Attrib1f} 至 {@link Shader.AttribI4uiv}
* @param type attribute 类型,可选 {@link GL2.ATTRIB_1f} 至 {@link GL2.ATTRIB_I4uiv}
* @returns attribute 常量的操作对象,可用于设置其值
*/
defineAttribute<T extends AttribType>(

View File

@ -69,7 +69,6 @@ Mota.require('var', 'loading').once('coreInit', () => {
</layer-group>
<Textbox id="main-textbox" {...mainTextboxProps}></Textbox>
<FloorChange id="floor-change" zIndex={50}></FloorChange>
<icon icon={13} animate></icon>
</container>
);
});

View File

@ -0,0 +1,93 @@
import { logger } from '@/core/common/logger';
import EventEmitter from 'eventemitter3';
export interface IStreamController<T = void> {
/**
* 开始流传输
*/
start(): Promise<T>;
/**
* 主动终止流传输
* @param reason 终止原因
*/
cancel(reason?: string): void;
}
export interface IStreamReader<T = any> {
/**
* 接受字节流流传输的数据
* @param data 传入的字节流数据,只包含本分块的内容
* @param done 是否传输完成
*/
pump(data: Uint8Array | undefined, done: boolean): void;
/**
* 开始流传输
* @param stream 传输流对象
* @param controller 传输流控制对象
*/
start(stream: ReadableStream, controller: IStreamController<T>): void;
/**
* 结束流传输
* @param done 是否传输完成,如果为 false 的话,说明可能是由于出现错误导致的终止
* @param reason 如果没有传输完成,那么表示失败的原因
*/
end(done: boolean, reason?: string): void;
}
interface StreamLoaderEvent {
data: [data: Uint8Array | undefined, done: boolean];
}
export class StreamLoader
extends EventEmitter<StreamLoaderEvent>
implements IStreamController<void>
{
/** 传输目标 */
private target: Set<IStreamReader> = new Set();
/** 读取流对象 */
private stream?: ReadableStream;
constructor(public readonly url: string) {
super();
}
/**
* 将加载流传递给字节流读取对象
* @param reader 字节流读取对象
*/
pipe(reader: IStreamReader) {
this.target.add(reader);
return this;
}
async start() {
const response = await window.fetch(this.url);
const stream = response.body;
if (!stream) {
logger.error(23);
return;
}
// 获取读取器
this.stream = stream;
const reader = response.body?.getReader();
this.target.forEach(v => v.start(stream, this));
// 开始流传输
while (true) {
const { value, done } = await reader.read();
this.target.forEach(v => v.pump(value, done));
if (done) break;
}
this.target.forEach(v => v.end(true));
}
cancel(reason?: string) {
if (!this.stream) return;
this.stream.cancel(reason);
this.target.forEach(v => v.end(false, reason));
}
}