2017-04-11 8 views
1

私は(私はノードの「コ」を使用しています)約束での作業に新たなんだので、私は、このコードで失敗しているもの全くわからない:に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; 
} 

ファイルを読み込んで変換し、少なくともループ内ではすべてが正しく表示されますが、ループから抜けるとデータが消えるようです。私はまた、ループ内から値の1つを返そうとしましたが、どちらも機能しません。

編集:私はそれを正直に言うと、非同期または同期だ場合、完全にはわからないhttps://github.com/trevordixon/excel.js : parseXlsxは、ここに「エクセル」のモジュールからです。これは、そのコードのようだ、と私は「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。また、ループ内で関数を定義するのは良い習慣ではありません。

関連する問題