Console.log显示数组但无法返回
Console.log shows array but can't be returned
我刚开始使用 promises(我在节点中使用 '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;
}
它读取文件,转换它,至少在循环中,它正确显示所有内容,但是一旦我们退出循环,数据似乎就消失了。我也尝试 return 循环中的值之一,但这也不起作用。
编辑:
parseXlsx 来自 'excel' 模块:https://github.com/trevordixon/excel.js
老实说,我不确定它是异步的还是同步的。这似乎是它的代码,我知道 'extractFiles' return 是一个承诺,但自从它通过 '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 是一个异步调用,因此您不会立即取回数据。
如何修复:
在回调中做事。
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;
}
只使用一个计数器,何时 return,试试这样的方法。
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++
});
}
}
所以这里发生的事情是您的代码只是运行那个 for 块,调用 parseXlsx
几次,但实际上从未等待它完成。
所以这就是为什么你的空数组日志排在第一位,然后是带有 'correct data' 的日志。查看 javascript 事件循环以更好地了解异步函数的工作原理。
您本质上需要的是在完成后解决的承诺,或者获得一个在完成后调用的回调函数。
当你的 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.
});
Node.js 是一个异步框架。在您的情况下发生的是 console.log(jsonData) 在 parseXlsx 之外的调用先于内部调用。您可以尝试这样的异步瀑布方法。
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;
});
}
您可以阅读更多相关信息 here。
PS。在循环内定义函数也不是一个好习惯。
我刚开始使用 promises(我在节点中使用 '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;
}
它读取文件,转换它,至少在循环中,它正确显示所有内容,但是一旦我们退出循环,数据似乎就消失了。我也尝试 return 循环中的值之一,但这也不起作用。
编辑: parseXlsx 来自 'excel' 模块:https://github.com/trevordixon/excel.js 老实说,我不确定它是异步的还是同步的。这似乎是它的代码,我知道 'extractFiles' return 是一个承诺,但自从它通过 '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 是一个异步调用,因此您不会立即取回数据。
如何修复:
在回调中做事。
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;
}
只使用一个计数器,何时 return,试试这样的方法。
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++
});
}
}
所以这里发生的事情是您的代码只是运行那个 for 块,调用 parseXlsx
几次,但实际上从未等待它完成。
所以这就是为什么你的空数组日志排在第一位,然后是带有 'correct data' 的日志。查看 javascript 事件循环以更好地了解异步函数的工作原理。
您本质上需要的是在完成后解决的承诺,或者获得一个在完成后调用的回调函数。
当你的 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.
});
Node.js 是一个异步框架。在您的情况下发生的是 console.log(jsonData) 在 parseXlsx 之外的调用先于内部调用。您可以尝试这样的异步瀑布方法。
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;
});
}
您可以阅读更多相关信息 here。
PS。在循环内定义函数也不是一个好习惯。