如何使用超时执行 fs.existsSync(path)

How to do fs.existsSync(path) with Timeout

我正在使用 TestCafe 和 Node.JS 编写自动化测试脚本。 其中一项测试是下载文件并验证下载是否完成。 我不想写硬编码

await t.wait(4000);

因为我的测试是基于数据驱动的框架,所以我可以为它提供大量数据以及大量不同的文件和文件类型。因此,文件大小可能会从几千字节到千兆字节不等。

这么写

await t.wait(4000);

可能对一个测试用例有效,但对其他测试用例几乎肯定会失败。

我正在使用依赖项 'downloads-folder' 来发现本地系统上下载文件夹的路径。从那里我寻找我希望存在的特定文件。它适用于下载速度快的小文本文件和小 zip 文件。但是,一旦我尝试下载一个包含大量数据的非常大的 zip 文件,它就会失败

if (fs.existsSync(zipFileNameAndPath)) {
    await t.expect(true).eql(true); // Report it as a success.
} else {
    console.log('file does NOT exist: ' + zipFileNameAndPath);
  await t.expect(false).eql(true); // Report it as a failure!
}

所以我的问题是:

有没有办法做类似的事情

if (fs.existsSync(zipFileNameAndPath){[ timeout: 50000000]}) {...} else {...}

由此产生的超时将作为动态超时工作,等着看文件何时找到,如果在超时到期之前找到,那么它将 return 为真,并且仅在超时期限之后已经过去了会不会return false?

我正在寻找一个不依赖于 Lodash 或 JQuery 并且在 ES6 中运行良好的同步答案。

问题是您在没有等待下载完成的情况下检查文件是否存在。您发布的代码很好 - 您需要确保在下载完成(或失败)之前不会调用它。

如何操作取决于您进行下载的方式。它可以像在执行下载的代码行上放置一个 'await' 一样简单。

我写了一个函数:

async function CheckFileExistsWithTimeDelay(t, timeDelay, fileNameAndPath) {
    for (var i = 0; i < timeDelay; i++) {
        console.log('Waited for a total of ' + i.toString() + ' microseconds');
        await t.wait(1);
        if (fs.existsSync(fileNameAndPath)) {
            // break;
            return;
        }
    }
};

那么该函数的调用者如下所示:

await Common.CheckFileExistsWithTimeDelay(t, 500000, zipFileNameAndPath);

当然你可以注释掉 console.log(...),我只是把它留在那儿,这样我就可以在等待调试时观看它。

当我 运行 它时,它在下载一个 59mb 的 zip 文件时等待了 7996 微秒,然后才成功继续执行脚本。

可以很容易地被打破;或 Return;取决于您是想将其保留为函数还是直接将其与脚本代码一起使用 in-line。

const filepath = 'YOUR_FILE.pdf';
const verifyDownload = async () => new Promise((resolve, reject) => {
    fs.watchFile(filepath, (curr, prev) => {
        if (fs.existsSync(filepath)) {
            fs.unwatchFile(filepath);
            resolve(true);
        }
     });
});

await t.expect(await verifyDownload()).ok("Could not download", { timeout: 30000 });