2016-01-14 87 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