【问题标题】:How to make sure one async function is completed before another starts in NodeJS?如何确保一个异步功能在另一个异步功能在 NodeJS 中启动之前完成?
【发布时间】:2021-08-13 10:35:57
【问题描述】:

我是新手,可能会遗漏一些琐碎的事情。

public async RunWorkFlow() {
    const zipFile = await DownloadZipFile(123, `abc`);
    await UnzipZippedArtifacts(zipFile);
}

当我尝试上述操作时,有时 unzip 方法会在下载完成之前启动,并导致尝试解压缩损坏的(半下载)文件。 DownloadZipFileUnzipZippedArtifacts 都是异步方法,我想确保 DownloadZipFileUnzipZippedArtifacts 开始之前完成。

解压的时候报错

Error: Corrupted zip: can't find end of central directory表示文件没有正确下载。



    private async DownloadZipFile(buildId: number, projectName: string) : Promise<string>
    {
        const buildApi = await this.api.getBuildApi();
        const artifactDetails = await buildApi.getArtifacts(buildId, projectName);
        const localZipFileName = buildId.toString() + `_` + artifactDetails[0]?.name + `_` + Date.now() + ".zip";
        const artifactStream = await buildApi.getArtifactContentZip(
            buildId, 
            artifactDetails[0]?.name, 
            projectName);

        const localZipFileStream = fs.createWriteStream(localZipFileName);
        await artifactStream
            .pipe(localZipFileStream)
            .on(`finish`, () => {
                localZipFileStream.close();
                this.logger.I(`Artifact zip file was download successfully for buildId ${buildId} in the project ${projectName}, filename is ${localZipFileName}`);                
            });
        
        return localZipFileName;
    }

【问题讨论】:

  • 你能显示你的DownloadZipFile()吗?您确定该功能在文件完全下载时结束还是仅在下载开始时结束?
  • 已添加DownloadZipFile()
  • 仍有大量代码需要理解/调试才能发布,但请检查artifactStream 的值以确保其正常工作,以及是否检查createWriteStream 中的路径以及最后一件事你的DownloadZipFile() 在调用它时缺少参数
  • @MohamedOraby 谢谢!在调试时我注意到 return 语句在调用 .on("finish") 方法之前执行,知道为什么会这样吗?我认为理想情况下 await 会让它在移动到下一行之前实现承诺。

标签: node.js async-await fs


【解决方案1】:

artifactStream.pipe(localZipFileStream).on(...) 没有返回 Promise,所以await-ing 它没有意义。它只注册一个回调(on 中的第二个参数)以在“完成”事件发生时调用。

为了从 DownloadZipFile 返回 Promise,您需要将 artifactStream.pipe(localZipFileStream).on(...) 包装在 Promise 中,然后在调用回调函数时解决:

private async DownloadZipFile(buildId: number, projectName: string) : Promise < string >
{
    const buildApi = await this.api.getBuildApi();
    const artifactDetails = await buildApi.getArtifacts(buildId, projectName);
    const localZipFileName = buildId.toString() + `_` + artifactDetails[0]?.name + `_` + Date.now() + ".zip";
    const artifactStream = await buildApi.getArtifactContentZip(
        buildId,
        artifactDetails[0]?.name,
        projectName);

    const localZipFileStream = fs.createWriteStream(localZipFileName);
    return new Promise(function (resolve, reject) {
        // resolve with location of saved file
        artifactStream
            .pipe(localZipFileStream)
            .on('finish', () => {
                localZipFileStream.close();
                this.logger.I(`Artifact zip file was download successfully for buildId ${buildId} in the project ${projectName}, filename is ${localZipFileName} `);

                resolve(localZipFileStream);
            });

    })
}

【讨论】:

  • 非常感谢,这成功了!如果可以的话,你能澄清一下我试图做什么但没有奏效吗?
  • 我在答案中添加了一条评论,可能会澄清它
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-10-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-04-01
  • 2021-09-23
相关资源
最近更新 更多