HarmonyOS 鸿蒙Next中求助,后端接口是分段的流式返回,怎么实现实时获取

HarmonyOS 鸿蒙Next中求助,后端接口是分段的流式返回,怎么实现实时获取 类似豆包或者deepseek这种流式返回的字段,我怎么才能返回一个获取一个,而不是要等所有内容全都返回完成才能一次性收到所有值?

cke_2896.png


更多关于HarmonyOS 鸿蒙Next中求助,后端接口是分段的流式返回,怎么实现实时获取的实战教程也可以访问 https://www.itying.com/category-93-b0.html

4 回复

可以使用HTTP流式传输,HTTP流式传输请求是指在处理HTTP响应时,可以一次只处理响应内容的一小部分,而不是一次性将整个响应加载到内存,这对于处理大文件、实时数据流等场景非常有用。

完整示例代码见:Http_case

  1. 导入HTTP流式传输所需模块
import { http } from '@kit.NetworkKit';
import { BusinessError } from '@kit.BasicServicesKit';
import { common } from '@kit.AbilityKit';
  1. 创建HTTP流式传输HttpRequest对象

调用createHttp()方法,创建HttpRequest对象。

// 每一个httpRequest对应一个HTTP请求任务,不可复用。
let httpRequest = http.createHttp();
  1. 按需订阅HTTP流式响应事件

服务器响应的数据在dataReceive回调中返回,可通过订阅该信息获取服务器响应的数据,其他流式响应事件可按需进行订阅。

// 用于订阅HTTP流式响应数据接收事件。
let res = new ArrayBuffer(0);
httpRequest.on('dataReceive', (data: ArrayBuffer) => {
  const newRes = new ArrayBuffer(res.byteLength + data.byteLength);
  const resView = new Uint8Array(newRes);
  resView.set(new Uint8Array(res));
  resView.set(new Uint8Array(data), res.byteLength);
  res = newRes;
  console.info('res length: ' + res.byteLength);
});

// 用于订阅HTTP流式响应数据接收完毕事件。
httpRequest.on('dataEnd', () => {
  console.info('No more data in response, data receive end');
});

// 订阅HTTP流式响应数据接收进度事件,下载服务器的数据时,可以通过该回调获取数据下载进度。
httpRequest.on('dataReceiveProgress', (data: http.DataReceiveProgressInfo) => {
  console.log("dataReceiveProgress receiveSize:" + data.receiveSize + ", totalSize:" + data.totalSize);
});

// 订阅HTTP流式响应数据发送进度事件,向服务器上传数据时,可以通过该回调获取数据上传进度。
httpRequest.on('dataSendProgress', (data: http.DataSendProgressInfo) => {
  console.log("dataSendProgress receiveSize:" + data.sendSize + ", totalSize:" + data.totalSize);
});
  1. 发起HTTP流式请求,获取服务端数据。
let streamInfo: http.HttpRequestOptions = {
  method: http.RequestMethod.POST, // 可选,默认为http.RequestMethod.GET,用于向服务器获取数据,而POST方法用于向服务器上传数据。
  // 开发者根据自身业务需要添加header字段。
     header: {
    'Content-Type': 'application/json'
     },
     // 当使用POST请求时此字段用于传递请求体内容,具体格式与服务端协商确定。
  extraData: "data to send",
  expectDataType: http.HttpDataType.STRING,// 可选,指定返回数据的类型。
  usingCache: true, // 可选,默认为true。
  priority: 1, // 可选,默认为1。
  connectTimeout: 60000, // 可选,默认为60000ms。
  readTimeout: 60000, // 可选,默认为60000ms。若传输的数据较大,需要较长的时间,建议增大该参数以保证数据传输正常终止。
  usingProtocol: http.HttpProtocol.HTTP1_1, // 可选,协议类型默认值由系统自动指定。
}

// 填写HTTP请求的URL地址,可以带参数也可以不带参数。URL地址需要开发者自定义。请求的参数可以在extraData中指定。
httpRequest.requestInStream("EXAMPLE_URL", streamInfo).then((data: number) => {
  console.info("requestInStream OK!");
  console.info('ResponseCode :' + JSON.stringify(data));
  // 取消订阅步骤3中订阅的事件,并调用destroy方法主动销毁。
  this.destroyRequest(httpRequest);
}).catch((err: Error) => {
  console.error("requestInStream ERROR : err = " + JSON.stringify(err));
  // 取消订阅步骤3中订阅的事件,并调用destroy方法主动销毁。
  this.destroyRequest(httpRequest); 
});
  1. 取消步骤3中订阅HTTP流式响应事件,并调用destroy()方法销毁流式HTTP请求

调用该对象的off()方法,取消订阅步骤3中的事件,并且当该请求使用完毕时,调用destroy()方法销毁,该方法调用的时机,可以参考步骤4中的示例代码。

public destroyRequest(httpRequest: http.HttpRequest) {
  // 取消订阅HTTP流式响应数据接收事件。
  httpRequest.off('dataReceive');
  // 取消订阅HTTP流式响应数据发送进度事件。
  httpRequest.off('dataSendProgress');
  // 取消订阅HTTP流式响应数据接收进度事件。
  httpRequest.off('dataReceiveProgress');
  // 取消订阅HTTP流式响应数据接收完毕事件。
  httpRequest.off('dataEnd');
  // 当该请求使用完毕时,调用destroy方法主动销毁。
  httpRequest.destroy();
}

更多关于HarmonyOS 鸿蒙Next中求助,后端接口是分段的流式返回,怎么实现实时获取的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


【背景知识】 HTTP流式传输(Streaming)允许客户端与服务器之间以流的形式进行数据交互,而无需等待所有数据准备完毕,能显著提升用户体验。流式传输适用于大文件的上传下载、直播、实时数据更新等场景。

【解决方案】

实现同步读写流使用示例:

  1. 导入模块。
import { rcp } from '@kit.RemoteCommunicationKit';
import { BusinessError } from '@kit.BasicServicesKit';
  1. 利用rcp.NetworkInputQueue创建同步写队列对象实现同步写功能。
function testNetworkInputQueue() {
  // 创建同步写队列对象
  const NetworkInputQueue = rcp.NetworkInputQueue;
  const networkInputQueue = new NetworkInputQueue();

  // 模拟文件分批上传场景
  let counter = 0;
  const interval = setInterval(() => {
    // 添加数据到同步写队列
    networkInputQueue.write('a counter ' + counter++);
    if (counter === 10) {
      clearInterval(interval);
      // 关闭同步写队列
      networkInputQueue.close();
    }
  }, 100);

  // 创建session开发者根据需要实际情况设置远程校验方式
  const session = rcp.createSession({
    requestConfiguration: {
      security: {
        remoteValidation: 'skip',
      },
    },
  });
  // 发起请求
  session.post('https://example.org/post', networkInputQueue).then((resp: rcp.Response) => {
    console.info(`Response success, ${resp}`);
  }).catch((err: BusinessError) => {
    console.info(`Response failed, the error code is ${err.code}, error message is ${err}`);
  }).finally(() => {
    // 关闭session
    session.close();
  });
}
  1. 利用rcp.NetworkOutputQueue创建同步读队列对象实现同步读功能。
function testNetworkOutputQueue() {
  // 创建同步读队列对象
  const NetworkOutputQueue = rcp.NetworkOutputQueue;
  const networkOutputQueue = new NetworkOutputQueue();
  // 创建session
  const session = rcp.createSession();
  // 配置请求流数据size
  const numOfChunks = 10;
  const chunkLength = 1000;
  const totalBytes = numOfChunks * chunkLength;
  // 发起同步读请求
  session.get('https://httpbin.org/bytes/' + totalBytes.toString(), networkOutputQueue).then((resp: rcp.Response) => {
    // 分段读取请求到的数据
    for (let i = 0; i < numOfChunks; i++) {
      // 开发者需要根据实际场景处理后续业务
      const chunk = networkOutputQueue.read(chunkLength);
      console.info(`The chunk is ${chunk}`)
    }
    console.info(`Response succeeded, ${resp}`)
  }).catch((err: BusinessError) => {
      console.error(`Response failed, error code is ${err.code}, error message is ${err}`)
  }).finally(() => {
    // 关闭session
    session.close();
  });
}

还可使用session.fetch接口,在入参request对象的headers里面设置请求头内容,content字段里面设置请求体内容,流式响应在destination字段里设置为Stream对象即可进行处理。

在HarmonyOS鸿蒙Next中,可通过Streaming API处理分段流式返回。使用HttpClient发起请求时,设置响应类型为流式读取。通过监听数据块事件,实时获取并处理每个分段数据。示例代码中需配置请求头支持流式传输,并在回调中逐段解析响应体。

在HarmonyOS Next中实现流式接口的实时获取,可以通过以下方式:

  1. 使用HTTP分块传输:后端接口应使用Transfer-Encoding: chunked响应头,将数据分成多个块(chunk)逐步返回。前端通过监听onDataReceived事件逐块接收数据。

  2. ArkTS异步流处理

    import http from '[@ohos](/user/ohos).net.http';
    
    async function fetchStreamData(url: string) {
      let request = http.createHttp();
      request.on('dataReceive', (data: ArrayBuffer) => {
        // 实时处理每个数据块
        let chunk = String.fromCharCode.apply(null, new Uint8Array(data));
        console.log('收到数据块:', chunk);
      });
    
      await request.request(url, {
        method: http.RequestMethod.GET,
        header: { 'Accept': 'text/event-stream' }
      });
    }
    
  3. Server-Sent Events (SSE): 若后端支持SSE协议,可使用EventSource

    let eventSource = new EventSource('your-api-url');
    eventSource.onmessage = (event) => {
      console.log('实时数据:', event.data);
    };
    
  4. WebSocket方案: 对于双向实时通信,建议使用WebSocket:

    import webSocket from '[@ohos](/user/ohos).net.webSocket';
    
    let ws = webSocket.createWebSocket();
    ws.on('message', (data: string | ArrayBuffer) => {
      console.log('收到消息:', data);
    });
    ws.connect('ws://your-websocket-url');
    

关键点:

  • 确保后端正确配置分块传输或SSE协议
  • 前端使用对应的事件监听机制
  • 对于JSON流,需要在客户端实现数据拼接和解析逻辑
  • 注意资源释放,在组件销毁时关闭连接

这种实现方式与豆包、DeepSeek等应用的流式响应原理一致,能够实现逐字或逐段实时显示效果。

回到顶部