2014-09-06 48 views
2

任何人都可以找出这个代码有什么问题吗?我试图写一小部分字节到一个文件,我得到的是一个零长度的文件,没有错误报告。为什么使用promise的异步IO生成一个零长度的文件?

我想在node.js中使用异步文件IO和bluebird promise来将一些数据写入本地文件。我已经使用回调函数成功编写了此函数的同步版本和异步版本。但是,因为回调版本嵌套在地狱里,并且有各种错误处理问题,并且不容易维护,所以我认为我会尝试使用promise的版本,因为这应该是它的优势(更好的错误处理,更少的嵌套,更容易顺序异步操作)。

不幸的是,承诺版本只导致零长度的文件。这里是承诺版本的代码:

// at initialization time 
var Promise = require('bluebird'); 
var fs = Promise.promisifyAll(require('fs')); 


    // code in a function 
    var header = new Buffer('[temperatures] {"formatVersion": "1", "fields": ["t", "atticTemp", "outsideTemp"]}\r\n'); 
    filename += ".new"; 
    console.log("async write started"); 
    var fd; 
    fs.openAsync(filename, "w", 438).then(function(ffd) { 
     fd = ffd; 
     return fs.writeAsync(fd, header, 0, header.length, null);    
    }).then(function(args /* [written, buffer] */) { 
     var written = args[0]; 
     console.log("bytes written =" + written); 
     if (written !== header.length) { 
      console.log("not all data written"); 
      throw new Error("not all data written"); 
     } 

     // lots more data to write here 

     return fs.closeAsync(fd); 
    }).then(function() { 
     fd = null; 
     console.log(" async write finished"); 
    }).catch(function(e) { 
     // if (fd) fs.closeAsync(fd); 
     console.log(e, "data.writeData() - error writing data (new format)"); 
    }); 

我已经做了一切我知道如何做调试。所有预期的console.log()错误消息都以所需顺序显示。我已经验证了所有返回值和参数。没有任何错误报告。在再次运行之前,我已经删除了以前的文件。我在我的回调版本中使用了相同的参数和文件名,工作得很好(这似乎排除了文件权限问题)。我重新启动了电脑(顺便说一句,这是一个树莓派)。

我很难过。我认为这一定是愚蠢的,我在使用承诺时做错了,但我不能为了我的生活而看到什么是错的。

+0

+1使用蓝鸟:) – simonzack 2014-09-06 04:23:41

+0

这适用于我。你能使它更具可重复性吗? – simonzack 2014-09-06 04:32:28

+0

@simonzack - 我必须看看我是否可以在独立的node.js应用程序中重现它。 – jfriend00 2014-09-06 04:52:41

回答

0

好的,我想通了。在应用程序的正常操作中调用该函数时,该函数可以很好地工作。而且,如果我查看它在应用程序仍在运行时生成的文件,则文件没问题。

但(这是问题发生的地方),我也在应用程序退出时调用此函数。而且,猜猜看,你不能在出口事件处理程序中使用这些类型的异步操作而不会造成问题。它只要创建新的空文件,然后应用程序退出,这是剩下的东西(只是磁盘上新创建的空文件)。

这个特殊的函数有一个参数传入以确定写入是否需要同步或异步完成(仅仅因为这个原因),而且我还没有写入新的promise类型代码的同步部分(我写过我用过的其他版本的同步版本)。

奇怪的谜解决了。而且,这是愚蠢的。没有什么直接与承诺,但它是一个异步问题。

另一个谜团是为什么我的代码是async,但使用回调而不是promise的版本没有显示这个问题?显然,它在流程退出之前完成了它的工作,但承诺版本没有。

+0

有趣。如果使用setTimout强制文件写入另一个事件线程,回调版本会发生什么?超时延迟的长度是否重要? – 2014-09-06 07:46:55

+1

对于这项运动,您是否愿意运行蓝鸟的Zalgo构建并查看它是否展现出与回调相同的行为?承诺提供异步保证,回调不会但Zalgo构建将它们删除。 – 2014-09-06 11:20:35

+0

(另外,这里要做的适当的事情可能是阻止和使用功能的同步版本,因为它在应用程序退出处理程序上) – 2014-09-06 11:22:20

相关问题