Console.log显示数组,但无法返回

我是新的承诺(我在节点中使用'co'),所以我不完全确定什么是失败的代码:

function* excelToJSON(excelFileNames) { var jsonData = []; for (let index = 0; index < excelFileNames.length; index++) { parseXlsx(excelFilesNames[index], function (err, data) { jsonData.push(data); console.log(jsonData); //***Shows data correctly }); } console.log(jsonData); //***Empty array return yield jsonData; } 

它读取文件,将其转换,至less在循环内,它显示正确的一切,但一旦我们走出循环的数据似乎消失。 我也试图从循环内返回一个值,但是这也不起作用。

编辑:parseXlsx是从'excel'模块在这里: https : //github.com/trevordixon/excel.js我不完全确定,如果是asynchronous或同步,说实话。 这似乎是它的代码,我知道'extractFiles'返回一个承诺,但因为它然后通过'parseXlsx'我不知道以后会发生什么:

 function parseXlsx(path, sheet, cb) { if (typeof cb === 'undefined') { cb = sheet; sheet = '1'; } extractFiles(path, sheet).then(function(files) { cb(null, extractData(files)); }, function(err) { cb(err); }); }; 

编辑2:我曾经解决它是几个答案的结合,谢谢大家。

 function* excelToJSON(excelFileNames) { return new Promise(function(resolve, reject) { var jsonData = []; if (excelFilesNames === null || excelFilesNames.length === 0) { reject(); } for (let index = 0; index < excelFilesNames.length; index++) { parseXlsx(excelFilesNames[index], function(err, data) { if (err) { throw err; } jsonData.push(data); if (jsonData.length === excelFilesNames.length) { resolve(jsonData); } }); } }); } 

所以这里发生的事情是,你的代码只是通过块来运行,几次调用parseXlsx ,但是从来没有真正的等待它完成。

所以这就是为什么你的空数组日志先来,然后有了“正确的数据”的日志。 查找JavaScript事件循环以更好地理解asynchronous函数的工作方式。

你基本上需要的是要么当你完成的时候解决的一个承诺,要么得到一个callback函数,当你完成的时候你会调用这个函数。

当你完成jsonData.push(data);时你就会知道jsonData.push(data); 只要你的excelFileNames数组被调用了很多次。

例如:

 function excelToJSON(excelFileNames) { var deferred = Promise.defer(); var jsonData = []; for (let index = 0; index < excelFileNames.length; index++) { parseXlsx(excelFilesNames[index], function (err, data) { jsonData.push(data); console.log(jsonData); //***Shows data correctly if (jsonData.length === excelFileNames.length) { deferred.resolve(jsonData); } }); } return deferred.promise; } // And use it as a promise: var exelToJsonPromise = excelToJSON(["apples.xlsx", "pears.xlsx]); exelToJsonPromise.then(function(jsonData){ console.log(jsonData); // Now this will have everything in it. }); 

只使用一个计数器和什么时候返回,尝试这样的事情。

 function* excelToJSON(excelFileNames) { var jsonData = []; var count=0; for (let index = 0; index < excelFileNames.length; index++) { parseXlsx(excelFilesNames[index], function (err, data) { jsonData.push(data); console.log(jsonData); //***Shows data correctly if(count==excelFileNames.length){ console.log(jsonData); return yield jsonData; } count++ }); } } 

原因:

parseXlsx是一个asynchronous调用,所以你不会立即得到数据。


怎么修:

在callback中做事情。

 function* excelToJSON(excelFileNames, callback) { var jsonData = []; for (let index = 0; index < excelFileNames.length; index++) { parseXlsx(excelFilesNames[index], function (err, data) { jsonData.push(data); console.log(jsonData); //***Shows data correctly callback(jsonData); // do what you want with the jsonData here. }); } // console.log(jsonData); //***Empty array // return yield jsonData; } 

Node.js是一个asynchronous框架。 你的情况是,parseXlsx之外的console.log(jsonData)在里面被调用。 你可以尝试像这样的asynchronous瀑布方法。

 var pushData = function (err, data) { jsonData.push(data); console.log(jsonData); }; function* excelToJSON(excelFileNames) { var jsonData = []; async.waterfall([ function(){ for (let index = 0; index < excelFileNames.length; index++) { parseXlsx(excelFilesNames[index], pushData); } } ], function() { console.log(jsonData); return yield jsonData; }); } 

你可以在这里阅读更多。

PS。 在循环内部定义一个函数也不是一个好习惯。