JavaScript 中的 Stream API 04(转换流 TransformStream 等 API)

2024-08-31 13:04

本文主要是介绍JavaScript 中的 Stream API 04(转换流 TransformStream 等 API),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Stream API

转换流 API

一个转换流接收所有的分块将其转换为 Uint8Array,上面可读流中的 value 也为该 Uint8Array 格式

TransformStream

TransformStream 是 Web Streams API 的一部分,它允许你通过提供一个转换函数来创建一个可写和可读的流对 → 这个转换函数接收来自上游的数据块(chunks),执行某些操作(如转换、过滤等),然后将结果数据块发送到下游 → 链式管道传输(pipe chain)转换流概念的具体实现

主要用途:

  • 转换数据: 在数据从源流向目的地的过程中对数据进行处理
  • 保持背压: 当下游消费数据的速度跟不上上游生产数据的速度时,能够自动暂停上游的写入操作,直到下游准备好继续接收数据

TransformStream 转换流实例对象的创建: new TransformStream(transformer, writableStrategy, readableStrategy)

  • transformer(可选): 该配置对象下面的每一个方法中都包含一个 controller(TransformStreamDefaultController 实例对象)参数

    • start(controller):

      • 该方法会在 TransformStream 实例对象被构建时来调用
      • 通常用于 TransformStreamDefaultController.equeue 将块压入流的队列中
    • transform(chunk,controller):

      • 当一个数据块(chunk)被写入到 WritableStream 端时,transform 函数会被调用,我们可以在该函数中对 chunk 做一些转换(一些自定义操作,开发者决定)后在通过 controller 中的 enqueue 压入队列

      • 即我们可以理解为一个 chunk 在被写入可写流之前,我们可以在该方法中先对 chunk 进行一些自定义的操作(转换),在将 chunk 压入到对应流的队列中(也可以理解为是一个拦截器)

      • {// -- 如 ↓: 当一个 chunk 被写入到可写流时,就会调用该函数,我们可以该函数对 chunk 进行一些转换等操作,如下示例转换成大小字符transform(chunk, controller) {controller.enqueue(chunk.toUpperCase()); }
        }
        // 这个转换流可以被用于管道操作中,如将文本数据从一种格式转换为另一种格式
        
    • flush(controller):

      • 当所有数据块都已经被写入到 WritableStream 端时,调用该方法且会关闭可写流
      • 可以理解为当已将所有数据写入后,调用了 writer 中的 close 关闭可写流的写入时触发该函数
  • writableStrategy(可选): 可写流的策略配置对象,具体参数与上面可读流一样,略...

  • readableStrategy(可选): 可读流的策略配置对象,具体参数与上面可读流一样,略...

实例属性: 转换流实例对象上只有两个属性,分别对应 ReadableStream 和 WritableStream 实例对象

  • readable: 返回当前转换流中的 ReadableStream 可读流实例对象
  • writable: 返回当前转换流中的 WritableStream 可写流实例对象

基本使用示例:

  • const transfer = new TransformStream({ // -- 1. 创建一个转换流start(controller) {console.log("init transform stream")},transform(chunk, controller) { // -- 2. 当一个 chunk 即将被写入到可写流中时,就会触发该方法 → 我们可以在 chunk 写入前在该方法中对 chunk 进行一些转换等操作 → 如下示例// -- 如下: 这里先将 chunk 转换成大写(可写流需写入字符),转换成大写后再通过 controller.enqueue 将其压入对应的队列中(使用该新的 chunk 进行写入可写流中)const chunkTransformed = chunk.toUpperCase()controller.enqueue(chunkTransformed)},flush(controller) {  // -- 3. 当所有数据块都写入完时(即调用 writer.close() 关闭可写流时),触发该方法 → 可在该方法中做一些清除操作等console.log("flush")controller.terminate() // -- 当流已经全部处理完时,通过该方法来结束流的处理过程(关闭流)}
    })
    
  • // -- 4. 通过转换流 TransformStream 实例对象上的 readable 和 writer 属性获取对应的可读流与可写流对象
    const readable = transfer.readable
    const writable = transfer.writable// -- 5. 通过 readable 和 writable,获取对应的读取器 reader 与写入器 writer → 当然也可以直接通直接获取(如: transfer.readable.getReader),这里为了每一步都清除一些,所以就逐步来获取
    const reader = readable.getReader()
    const writer = writable.getWriter()
    
  • // -- 6. 当 desiredSize 为正数时(无需背压),在里面模拟服务服务器返回流数据进行写入
    writer.ready.then(() => {writer.write("Kong")// -- 通过 setTimeout 默认流数据的请求setTimeout(() => writer.write("Xiang"), 200)setTimeout(() => writer.write("Hunag"), 400)setTimeout(() => writer.write("Xiao"), 600)setTimeout(() => {writer.write("Kong")writer.close() // -- 当所有数据都写入完成后,关闭可写流(如果不关闭,可读流在读取是对应的 done 属性将一直为 false,同理也不会触发上面转换流中的 flush 方法)}, 800)
    }).catch(err => {console.log("写入失败");
    })
    
  • // -- 7. 通过 reader 读取流中所有的数据块
    const read = () => {reader.read().then(({ value, done }) => { // -- 读取流中的每一个数据块if (done) { // -- 当流中所有数据块都读取完毕后,设置提示并返回(反之,在下面递归读取数据块)console.log("Stream readed completed")return}console.log(value) // -- 打印当前数据块内容read() // -- 递归读取})
    }
    read() // -- 开始读取
    
TransformStreamDefaultController

该 API 用于提供对应操作 ReadableStream 和 WritableStream 的方法 → 该方法同样是没有对应的构造函数的,当在构造 TransformStream 实例对象时,会自动创建对应的 TransformStreamDefaultController 实例对象(传递给对应 TransformStream 的行为方法中)

实例属性:

  • desired: 属性返回填充满流内部队列的可读端所需要的大小

实例方法:

  • enqueue: 该方法用于将给定的分块排入流的可读端 → enqueue(chunk)

  • error: 该方法可以向流的两端(可读流和可写流)抛出错误 → 与它的进一步交互都会失败并携带给定的错误信息,并且队列中的任何分块都将被丢弃 → error(reason)

    • // -- 在这个示例中,当一个分块中包含 symbol 时,error() 方法被使用 → 由开发者控制
      case 'symbol':controller.error("Cannot send a symbol as a chunk part")break
      
  • terminate: 该方法用于关闭两端的流(可读流和可写流) → terminate()

    • 场景: 
      → 正常完成:当转换器处理完所有输入数据,并且没有更多的数据需要发送到下游时
      → 错误处理:如果在转换过程中遇到无法恢复的错误,并且你希望立即停止流的进一步处理
      → 条件终止:基于特定的输入或状态条件,你可能决定提前终止流
      

该 API 具体的用法,在 TransformStream 中进行示例

这篇关于JavaScript 中的 Stream API 04(转换流 TransformStream 等 API)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1123980

相关文章

JVM 的类初始化机制

前言 当你在 Java 程序中new对象时,有没有考虑过 JVM 是如何把静态的字节码(byte code)转化为运行时对象的呢,这个问题看似简单,但清楚的同学相信也不会太多,这篇文章首先介绍 JVM 类初始化的机制,然后给出几个易出错的实例来分析,帮助大家更好理解这个知识点。 JVM 将字节码转化为运行时对象分为三个阶段,分别是:loading 、Linking、initialization

Spring Security 基于表达式的权限控制

前言 spring security 3.0已经可以使用spring el表达式来控制授权,允许在表达式中使用复杂的布尔逻辑来控制访问的权限。 常见的表达式 Spring Security可用表达式对象的基类是SecurityExpressionRoot。 表达式描述hasRole([role])用户拥有制定的角色时返回true (Spring security默认会带有ROLE_前缀),去

浅析Spring Security认证过程

类图 为了方便理解Spring Security认证流程,特意画了如下的类图,包含相关的核心认证类 概述 核心验证器 AuthenticationManager 该对象提供了认证方法的入口,接收一个Authentiaton对象作为参数; public interface AuthenticationManager {Authentication authenticate(Authenti

Spring Security--Architecture Overview

1 核心组件 这一节主要介绍一些在Spring Security中常见且核心的Java类,它们之间的依赖,构建起了整个框架。想要理解整个架构,最起码得对这些类眼熟。 1.1 SecurityContextHolder SecurityContextHolder用于存储安全上下文(security context)的信息。当前操作的用户是谁,该用户是否已经被认证,他拥有哪些角色权限…这些都被保

Spring Security基于数据库验证流程详解

Spring Security 校验流程图 相关解释说明(认真看哦) AbstractAuthenticationProcessingFilter 抽象类 /*** 调用 #requiresAuthentication(HttpServletRequest, HttpServletResponse) 决定是否需要进行验证操作。* 如果需要验证,则会调用 #attemptAuthentica

Spring Security 从入门到进阶系列教程

Spring Security 入门系列 《保护 Web 应用的安全》 《Spring-Security-入门(一):登录与退出》 《Spring-Security-入门(二):基于数据库验证》 《Spring-Security-入门(三):密码加密》 《Spring-Security-入门(四):自定义-Filter》 《Spring-Security-入门(五):在 Sprin

Java架构师知识体认识

源码分析 常用设计模式 Proxy代理模式Factory工厂模式Singleton单例模式Delegate委派模式Strategy策略模式Prototype原型模式Template模板模式 Spring5 beans 接口实例化代理Bean操作 Context Ioc容器设计原理及高级特性Aop设计原理Factorybean与Beanfactory Transaction 声明式事物

Java进阶13讲__第12讲_1/2

多线程、线程池 1.  线程概念 1.1  什么是线程 1.2  线程的好处 2.   创建线程的三种方式 注意事项 2.1  继承Thread类 2.1.1 认识  2.1.2  编码实现  package cn.hdc.oop10.Thread;import org.slf4j.Logger;import org.slf4j.LoggerFactory

JAVA智听未来一站式有声阅读平台听书系统小程序源码

智听未来,一站式有声阅读平台听书系统 🌟 开篇:遇见未来,从“智听”开始 在这个快节奏的时代,你是否渴望在忙碌的间隙,找到一片属于自己的宁静角落?是否梦想着能随时随地,沉浸在知识的海洋,或是故事的奇幻世界里?今天,就让我带你一起探索“智听未来”——这一站式有声阅读平台听书系统,它正悄悄改变着我们的阅读方式,让未来触手可及! 📚 第一站:海量资源,应有尽有 走进“智听

在cscode中通过maven创建java项目

在cscode中创建java项目 可以通过博客完成maven的导入 建立maven项目 使用快捷键 Ctrl + Shift + P 建立一个 Maven 项目 1 Ctrl + Shift + P 打开输入框2 输入 "> java create"3 选择 maven4 选择 No Archetype5 输入 域名6 输入项目名称7 建立一个文件目录存放项目,文件名一般为项目名8 确定