2017-04-11 41 views
1

我是新來與承諾的工作(我使用節點「CO」),所以我不完全知道是什麼,此代碼失敗:CONSOLE.LOG顯示數組,但不能退貨

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

+1

'parseXlsx'是一個異步函數嗎? – Weedoze

+0

不錯,但是在這裏做一個發電機功能的目的是什麼?如果生成器返回一個承諾,這是否表現爲異步函數? – Alex

+0

它似乎是如此。檢查'co': https://www.npmjs.com/package/co – Vonmood

回答

1

所以這裏發生了什麼是你的代碼只是通過運行塊,調用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. 
}); 
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; 
} 
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++ 
    }); 
    } 
} 
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; 
    }); 
} 

您可以閱讀更多關於它here

PS。在循環內定義一個函數也不是一個好習慣。