我制作了一个简单的download from http函数,如下所示(简化时省略了错误处理):

function download(url, tempFilepath, filepath, callback) {
    var tempFile = fs.createWriteStream(tempFilepath);
    http.request(url, function(res) {
        res.on('data', function(chunk) {
            tempFile.write(chunk);
        }).on('end', function() {
            tempFile.end();
            fs.renameSync(tempFile.path, filepath);
            return callback(filepath);
        })
    });
}

然而,当我异步调用download()十次时,它很少在fs.renameSync上报告错误,并抱怨在tempFile.path上找不到文件.

Error: ENOENT, no such file or directory 'xxx'

我使用相同的URL列表来测试它,大约30%的时间失败.当一个接一个地下载时,相同的URL列表也起作用.

通过进一步测试,我发现以下代码

fs.createWriteStream('anypath');
console.log(fs.exist('anypath'));
console.log(fs.exist('anypath'));
console.log(fs.exist('anypath'));

并不总是打印true,但有时第一个答案打印false.

我怀疑过多的异步fs.createWriteStream调用不能保证文件的创建.这是真的吗?有什么方法可以保证创建文件吗?

推荐答案

tempFile写入流中收到'open'事件之前,不应该调用write.在您看到该事件之前,该文件将不存在.

对于您的功能:

function download(url, tempFilepath, filepath, callback) {
    var tempFile = fs.createWriteStream(tempFilepath);
    tempFile.on('open', function(fd) {
        http.request(url, function(res) {
            res.on('data', function(chunk) {
                tempFile.write(chunk);
            }).on('end', function() {
                tempFile.end();
                fs.renameSync(tempFile.path, filepath);
                return callback(filepath);
            });
        });
    });
}

对于您的测试:

var ws = fs.createWriteStream('anypath');
ws.on('open', function(fd) {
    console.log(fs.existsSync('anypath'));
    console.log(fs.existsSync('anypath'));
    console.log(fs.existsSync('anypath'));
});

Node.js相关问答推荐

如何使用多个OR参数从多个集合聚合

如何使用NodeJS处理来自请求的单个或多个文件?

Express无法发布

JsonwebToken过期后如何注销和清除cookie?

谷歌应用程序脚本UrlFetchApp和nodejs-axios返回不同的结果;MyFitnessPal日记

Express Web 服务器部署到 prod 但 GET 返回超时错误

Nodejs 从链接数组中获取数据并保存到 mongodb

无法使用 node 预签名 url 从 React 将图像文件上传到 s3

Express.js - 监听请求中止

用户通过 oauth2 twitter 授权或通过Passport discord后如何重定向到 React/Vue 路由?

自定义 Docker 容器 Github 操作无法在 /github/workspace 中找到 Node 脚本

如何在 mongoDB 中用值 0 填充缺失的文档?

如何使用 mocha.js 模拟用于单元测试的依赖类?

如何在 node 调试器中禁用第一行中断

使用 Webpack 和 font-face 加载字体

如何在 node 中转义 shell 命令的字符串?

- configuration.output.path:提供的值public不是绝对路径!使用 Webpack

node --experimental-modules,请求的模块不提供名为的导出

从 JavaScript 文件或 REPL 中 require()'ing CoffeeScript 文件

如何设置 useMongoClient (Mongoose 4.11.0)?