如何确保在 NodeJS 中一个异步函数在另一个异步函数开始之前完成?

How to make sure one async function is completed before another starts in NodeJS?

我是新手,可能遗漏了一些微不足道的东西。

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

当我尝试上述操作时,有时解压缩方法会在下载完成之前启动,并导致尝试解压缩损坏的(下载一半的)文件。 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;
    }

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

为了 return 来自 DownloadZipFile 的 Promise,您需要将 artifactStream.pipe(localZipFileStream).on(...) 包装在 Promise 中,然后在调用回调函数时解析该 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);
            });

    })
}