2

そのため、私は最近、プロミスと、JavaScript の非同期動作によるプロミスの背後にある目的を理解しようとしています。私は理解していると「思っています」が、何かを約束して将来の値を返し、新しいコードブロックを実行して何か他のことをする方法にまだ苦労しています。私が使用している2つの主要なノードモジュール:

  • pg-約束
  • エクセルズ

私がやりたいのは、ファイルを読み取り、完全に読み取ったら、DB コマンドを実行する各ワークシートを繰り返すことです。次に、すべてのワークシートが処理されたら、戻って、私が読んだ元のファイルを削除します。これが私が持っているコードです。 複数のワークシートがある場合でも、すべてがデータベースに正常に書き込まれるまで機能しています。私が取り組んでいないのは、すべてのワークシートが完全に処理されたときにそれを識別し、ファイルを削除するように設定することです

workbook.csv.readFile(fileName)
            .then(function () {
                // this array I was going to use to somehow populate a true/false array.  
                // Then when done with each sheet, push a true into the array.  
                // When all elements were true could signify all the processing is done... 
                // but have no idea how to utilize this!  
                // So left it in to take up space because wtf...
                var arrWorksheetComplete = [];

                workbook.eachSheet(function (worksheet) {
                    console.log(worksheet.name);
                    db.tx(function (t) {
                        var insertStatements = [];
                        for (var i = 2; i <= worksheet._rows.length; i++) {
                            // here we create a new array from the worksheet, as we need a 0 index based array.
                            // the worksheet values actually begins at element 1.  We will splice to dump the undefined element at index 0.
                            // This will allow the batch promises to work correctly... otherwise everything will be offset by 1
                            var arrValues = Array.from(worksheet.getRow(i).values);
                            arrValues.splice(0, 1);

                            // these queries are upsert.  Inserts will occur first, however if they error on the constraint, an update will occur instead.
                            insertStatements.push(t.one('insert into rq_data' +
                                '(col1, col2, col3) ' +
                                'values($1, $2, $3) ' +
                                'ON CONFLICT ON CONSTRAINT key_constraint DO UPDATE SET ' +
                                '(prodname) = ' +
                                '($3) RETURNING autokey',
                                arrValues));
                        }
                        return t.batch(insertStatements);
                    })
                    .then(function (data) {
                        console.log('Success:', 'Inserted/Updated ' + data.length + ' records');
                    })
                    .catch(function (error) {
                        console.log('ERROR:', error.message || error);
                    });
                });
            });

言えるようになりたい

.then(function(){
    // everything processed!
    removeFile(fileName)
    // this probably also wouldn't work as by now fileName is out of context?
});

しかし、約束の中に約束があると、私は非常に混乱します..私は、基本的に.eachSheet関数内にネストされた約束であるdb.tx呼び出しを持っています。愚かなプログラマーが理解できるように助けてください!これで何時間も壁に頭をぶつけてきました。:)

4

1 に答える 1

0

私の理解が正しければ、あなたは約束を連鎖させようとしています。

Promises のアンチパターンに関するこのすばらしい記事を読むことをお勧めします(「コレクションのカーファッフル」セクションを参照)。

promise を連続して実行する必要がある場合、この記事ではreduceを使用することをお勧めします。

スニペットを次のように書き直します。

workbook.csv.readFile(fileName).then(function () {

  processWorksheets().then(function() {
    // all worksheets processed!
  });

});

function processWorksheets() {
    var worksheets = [];

    // first, build an array of worksheet
    workbook.eachSheet(function (worksheet) {
        worksheets.push(worksheet);
    }); 

    // then chain promises using Array.reduce
    return worksheets.reduce(function(promise, item) {
        // promise is the the value previously returned in the last invocation of the callback.
        // item is a worksheet

        // when the previous promise will be resolved, call saveWorksheet on the next worksheet
        return promise.then(function(result) {
            return saveWorksheet(item, result);
        });        

    }, Promise.resolve()); // start chain with a 'fake' promise
}

// this method returns a promise
function saveWorksheet(worksheet, result) {

    return db.tx(function (t) {

      var insertStatements = [];
      for (var i = 2; i <= worksheet._rows.length; i++) {
        // here we create a new array from the worksheet, as we need a 0 index based array.
        // the worksheet values actually begins at element 1.  We will splice to dump the undefined element at index 0.
        // This will allow the batch promises to work correctly... otherwise everything will be offset by 1
        var arrValues = Array.from(worksheet.getRow(i).values);
        arrValues.splice(0, 1);

        // these queries are upsert.  Inserts will occur first, however if they error on the constraint, an update will occur instead.
        insertStatements.push(t.one('insert into rq_data' +
                                    '(col1, col2, col3) ' +
                                    'values($1, $2, $3) ' +
                                    'ON CONFLICT ON CONSTRAINT key_constraint DO UPDATE SET ' +
                                    '(prodname) = ' +
                                    '($3) RETURNING autokey',
                                    arrValues));
      }

      return t.batch(insertStatements);
    })
    // this two below can be removed...
    .then(function (data) {
       return new Promise((resolve, reject) => { 
          console.log('Success:', 'Inserted/Updated ' + data.length + ' records');
          resolve();
       });
    })
    .catch(function (error) {
        return new Promise((resolve, reject) => {
        console.log('ERROR:', error.message || error);
        reject();
      });
    });

}

promiseモジュールを含めることを忘れないでください:

var Promise = require('promise');

コードをテストしていないため、タイプミスが含まれている可能性があります。

于 2016-10-16T13:53:01.757 に答える