1

我不熟悉使用承诺(我在节点中使用'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;
}

它读取文件,转换它,至少在循环中,它正确显示了所有内容,但是一旦我们退出循环,数据似乎就消失了。我也尝试从循环中返回其中一个值,但这也不起作用。

编辑: parseXlsx 来自这里的“excel”模块:https ://github.com/trevordixon/excel.js 老实说, 我不完全确定它是异步的还是同步的。这似乎是它的代码,我知道“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);
  });
};

EDIT2:我用来解决它是几个答案的组合,谢谢大家。

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);
        }
      });
    }
  });
}

4

4 回答 4

3

只使用一个柜台和何时返回,尝试这样的事情。

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++
    });
  }
}
于 2017-04-11T08:42:26.920 回答
2

所以这里发生的情况是,您的代码只是通过 for 块运行,调用parseXlsx了几次,但实际上从未等待它完成。

所以这就是为什么你的空数组日志首先出现,然后是带有“正确数据”的日志。查看 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.
});
于 2017-04-11T08:47:14.610 回答
2

原因:

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;
}
于 2017-04-11T08:41:07.470 回答
1

Node.js 是一个异步框架。在您的情况下发生的事情是 parseXlsx 外部的 console.log(jsonData) 在内部调用之前被调用。您可以尝试像这样的异步瀑布方法。

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。在循环内定义函数也不是一个好习惯。

于 2017-04-11T09:01:21.477 回答