使用Got流式下载.ts文件时await未生效,无法顺序执行任务
实现Got流式下载的串行执行方案
你的问题核心在于downloadFileWithGot函数没有真正等待流式下载完成:
got.stream()返回的是流对象,不是Promise,await它只会立即获取到流对象,不会等待下载过程结束pipe()返回的是目标写入流,同样不是Promise,await这个操作也不会等待文件写入完成
要实现串行下载,需要把流式下载的过程包装成真正能等待完成的Promise,修改如下:
修改工具文件中的downloadFileWithGot函数
import { createWriteStream } from 'fs'; import got from 'got'; export async function downloadFileWithGot(url, outputLocationPath, options) { console.log('entered inside fn'); return new Promise((resolve, reject) => { const writeStream = createWriteStream(outputLocationPath); const stream = got.stream(url, options); // 监听请求错误 stream.on('error', (err) => { console.error(`下载请求出错:${err.message}`); writeStream.close(); reject(err); }); // 监听写入错误 writeStream.on('error', (err) => { console.error(`文件写入出错:${err.message}`); stream.destroy(); reject(err); }); // 监听写入完成 writeStream.on('finish', () => { console.log('successfully wrote to file'); resolve(writeStream); }); console.log('got pipe resp'); stream.pipe(writeStream); }); }
主文件循环优化(保持串行逻辑)
const allFileLines = allFileContents.split(/\r?\n/); async function makeApiCall(){ // allFileLines是普通数组,用for...of即可,无需for await for(const line of allFileLines){ if (line.startsWith("https")) { const fileName = new URL(line).pathname.split('/')[1]; const downloadPathAndFile = `${download_path}${dirName}/${fileName}`; console.log(`Downloading file : ${fileName}`); await downloadFileWithGot(line, downloadPathAndFile, getOptions(line)) } } } await makeApiCall();
逻辑说明
- 用Promise包裹整个流操作,通过监听
stream的error、writeStream的error和finish事件来控制Promise的状态 - 只有当文件写入完成触发
finish事件时,Promise才会resolve,此时await才会结束,循环进入下一次迭代 - 任何环节出错都会触发reject,你可以根据需要添加错误处理逻辑(比如捕获异常后继续下一个文件下载)
内容的提问来源于stack exchange,提问作者suhasa
相关产品推荐
相关产品推荐

