2014-09-06 56 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

相關問題