2016-01-14 126 views
2

我是新入javascript,目前我正在學習回調我的腳本。這個腳本應該返回減少的話中的對象回調問題

的陣列

var fs = require('fs') 
 
var dict = ['corpus.txt','corpus1.txt','corpus2.txt']; 
 

 
mapping(dict, function(error,data){ 
 
\t if(error) throw error 
 
\t console.log(data) 
 
}) 
 

 
function mapping(list, callback){ 
 
\t var txtObj = [] 
 
\t list.forEach(function (val) { 
 
\t \t readFile(val, function(error,data){ 
 
\t \t \t txtObj.push(data) 
 
\t \t }) 
 
\t }) 
 
\t function readFile(src, cb){ 
 
\t \t fs.readFile(src,'utf8', function (error,data) { 
 
\t \t \t if (error) return callback(error,null) 
 
\t \t \t return mapred(data) 
 
\t \t }) 
 
\t } 
 
\t return callback(null,txtObj) 
 
}

但它返回空數組。任何幫助,將不勝感激。 謝謝!

+0

你需要不是立即調用'callback',而是稍後調用'readFile'。這有點棘手,因爲你有多個文件。試着讓它首先使用單個文件。一旦你明白了這是如何工作的,回到另一個問題就是如何使它與許多人合作。 – Thilo

回答

3
`fs.readFile` 

是一個異步函數,在它完成並調用結果回調函數之前,您將返回空的txtObj數組。

如何解決?

撥打return callback(null,txtObj)fs.readFile已完成運行。

此外,由於您正在逐個項目數組上運行異步功能,因此它可能無法按照您的方式工作。可能想要使用modudlesasync在nodejs

這裏是一個異步版本使用模塊異步。 同步文件操作強烈反對 :)

var fs = require('fs') 
var dict = ['corpus.txt','corpus1.txt','corpus2.txt']; 

mapping(dict, function(error,data){ 
    if(error) throw error 
    console.log(data) 
}) 

function mapping(list, callback){ 
    var txtObj = [], 
     async = require('async'); 

    async.each(list, readFile, function(err) { 
     callback(err,txtObj) 
    }); 

    function readFile(src, cb) { 
     fs.readFile(src,'utf8', function (error,data) { 
      if (error) { 
       cb(error); 
      } 
      else { 
       txtObj.push(mapred(data)); 
       cb(null); 
      } 
     }) 
    } 
} 

編輯:你可以做到這一點沒有異步,但它是有點髒了是不是?也是它的確定,如果您刪除在foreach內部的自我調用函數,我包括在內,以便您可以訪問VAL,回調做

var fs = require('fs') 
var dict = ['corpus.txt','corpus1.txt','corpus2.txt']; 

mapping(dict, function(error,data){ 
    if(error) throw error 
    console.log(data) 
}) 

function mapping(list, callback){ 
    var txtObj = [], 
     counter = list.length, 
     start = 0; 

    list.forEach(function (val) { 
     (function(val) 
      readFile(val, function(error,data) { 
       txtObj.push(data); 
       start++; 
       if(error || (start === counter)) { 
        callback(error,txtObj); 
       } 

     }))(val); 
    }) 

    function readFile(src, cb) { 
     fs.readFile(src,'utf8', function (error,data) { 
      if (error) { 
       cb(error); 
      } 
      else { 
       txtObj.push(mapred(data)); 
       cb(null); 
      } 
     }) 
    } 
} 
+0

我對使用異步知道一點點,但我正在尋找更多使用回調的「優雅」方式。沒有異步的解決方案嗎? – pacific01

+0

@ pacific01:我使用異步模塊編輯我的答案,但使用異步 - 它更簡單易讀 – Oxi

+0

謝謝@Oxi! – pacific01

1
即使

你得到一個空數組結果的原因是,你在readFile函數有機會填充數組之前正在執行回調。您正在執行多個異步操作,但在繼續之前不會讓它們完成。

如果只有一個異步操作,你會打電話callback()在READFILE的回調函數,但你需要在調用callback()之前執行多個異步操作,您應該考慮使用fs.readFileSync()

有時會同步無法避免。

function mapping(list, callback) 
{ 
    var txtObj = [] 
    list.forEach(function(val) 
    { 
     try { txtObj.push(mapred(fs.readFileSync(val, 'utf8'))) } 
     catch(err) { callback(err) } 
    }) 
    callback(null, txtObj) 
} 
+0

嗯...根據使用情況,'readFileSync'可能會非常好,但它肯定可以在這裏避免。你只需要一些工具來管理「期貨清單」(我同意這對初學者來說可能有點令人生畏)。 – Thilo

+0

謝謝你的見解:) – pacific01