在NodeJS中完成下载和文件保存后从异步函数返回

Posted

技术标签:

【中文标题】在NodeJS中完成下载和文件保存后从异步函数返回【英文标题】:Return From Async Function After Download and File Save are Complete in NodeJS 【发布时间】:2020-07-29 03:25:56 【问题描述】:

我有一系列类似这样的事件:

//Download a file and write it to disk
await downloadSyncFile(user, downloadURL)
//Use the file...
await useTheFile() //Crash! The file is only partially there! Dangit!

在文件实际在磁盘上之前,我的代码会继续运行。这是我的下载功能:

async function downloadSyncFile(user, downloadURL)
  //Setup download path
  let path = './data/'+user+'/file.whatevs'

  try
    //Download and save file
    let stream = fs.createWriteStream(path)
    let response = await axios.get(downloadURL,  responseType: 'stream' )
    response.data.pipe(stream)

    await new Promise(fulfill => stream.on('finish', fulfill))


  catch(error)
    console.log('downloadSyncFile Error: '+error)
    return  success: false, message: error 
  

axios 下载完成后,downloadSyncFile() 函数似乎正在返回,但写入磁盘尚未完成。

如何确保在downloadSyncFile() 返回之前将文件安全地写入磁盘?

【问题讨论】:

您在这里吞下了错误——您确定您的downloadSyncFile 没有返回success:false,message:... 对象(您的catch 语句的返回值)?您是否已验证(例如,使用另一个事件处理程序)finish 事件在承诺解决之前触发? 【参考方案1】:

您不会从 downloadSyncFile() 返回 Promise。

改变

await new Promise(fulfill => stream.on('finish', fulfill));

return new Promise(fulfill => stream.on('finish', fulfill));

最好这样写:

async function downloadSyncFile(user, downloadURL) 
    return new Promise((fulfill, reject) => 
        let path = './data/' + user + '/file.whatevs';
        let stream = fs.createWriteStream(path);
        let response = await axios.get(downloadURL,  responseType: 'stream' );
        response.data.pipe(stream);
        stream.on('finish', fulfill));
        stream.on('error', reject); // presumably
    );

所有内容都包含在 new Promise(...) 中,try catch() 是不必要的,因为任何同步错误都会导致 Promise 被拒绝。

【讨论】:

谢谢!这很有帮助。 :)

以上是关于在NodeJS中完成下载和文件保存后从异步函数返回的主要内容,如果未能解决你的问题,请参考以下文章

NodeJS 异步回调未完成和渲染把手模板

nodejs基础 -- 回调函数

nodejs下载文件先判断内存是不是够用

Nodejs学习笔记

nodejs学习笔记 --回调函数

NodeJS Express 异步/等待