2017-11-17 10 views
0

ノードJSアプリケーションを作成しました。データベースから100000を超えるレコードを明示的にダウンロードしています。リクエストが進行中に、前のリクエストが完了しない限り、応答しない別のブラウザから同じアプリケーションでログインしようとします。何か案が ?イベントループやスレッドとは何か? ここに私の論理があります。 ステップ1でAPIを取得し、ステップ2でAPI呼び出しのデータベースレイヤーを取得します。データベースは21レコードしか返しません。明示的に100000 * 21をループしてjson2csvの負荷をテストするだけです。そうしている間、サーバーへの他の要求は、最後の処理が完了するまで応答しません。ノードJSリクエストが他のリクエストをブロックする

Step 1: 

router.get('/report/downloadOverdueTrainings/:criteria', function (req, res, next) { 
     var overDueTrainings = []; 
     var reportManager = new ReportManager(); 
     var result = reportManager.getOverdueTrainings(JSON.parse(req.params.criteria)); 
     result.then(function (result) { 
      var fields = ['Over Due Trainings']; 
      for (var i = 0; i < 100000; i++) { //Testing purpose 
       for (var training of result) { 
        overDueTrainings.push({ 
         'Over Due Trainings': training.OverDueTrainings 
        }) 
       } 
      } 
      json2csv({ 
       data: overDueTrainings, 
       fields: fields 
      }, function (err, csv) { 
       if (err) 
        throw err; 
       res.setHeader('Content-disposition', 'attachment; filename=OverdueTrainings.csv'); 
       res.set('Content-Type', 'text/csv'); 
       res.send(csv); 
      }); 
     }).catch(function (err) { 
      next(err); 
     }); 
    }); 

Step 2: Database Logic 
var xtrDatabaseConnection =require('./xtrDatabaseConnection').XTRDatabaseConnection; 
     ReportData.prototype.getOverdueTrainings = async function (params) { 
     var connection = new xtrDatabaseConnection(); 
     var sequelize = connection.getSequelize(); 
     try { 
      var query = "CALL report_getOverdueTrainings(:p_CourseCode,:p_Revision,:p_RevisionNo,:p_UserGroup,:p_Username,:p_Status,:p_SortColoumnNo,:p_SortColoumnDirection,:p_callType,:p_StartIndex,:p_PageSize)"; 
      var replacements = { 
       p_CourseCode: params.CourseCode, 
       p_Revision: params.Revision, 
       p_RevisionNo: (params.RevisionNo == '' || params.RevisionNo == null) ? 0 : params.RevisionNo, 
       p_UserGroup: params.UserGroup, 
       p_Username: params.Username, 
       p_Status: params.Status, 
       p_SortColoumnNo: params.SortColoumnNo, 
       p_SortColoumnDirection: params.SortColoumnDirection, 
       p_callType: params.callType, 
       p_StartIndex: params.startIndex, 
       p_PageSize: params.pageSize 
      }; 
      //console.log(replacements); 
      return await connection.executeQuerySequelize(sequelize, query, Sequelize.QueryTypes.RAW, replacements); 
     } catch (e) { 
      throw (e); 
     } finally { 
      //To close connections 
      sequelize.connectionManager.close().then(() => console.log('Connection Closed')); 
     } 
    } 




XTRDatabaseConnection.prototype.executeQuerySequelize = function (sequelize, query, queryType, replacements) { 
    return sequelize.authenticate() 
     .then(() => { 
      return sequelize.query(query, { 
       replacements: replacements, 
       type: queryType 
      }). 
      then(result => result) 
       .catch(err => { 
        throw (err); 
       }); 
     }) 
     .catch(err => { 
      xtrUtility.logErrorsToWinstonTransports('Unable to connect to the database or some error occurred while executing your query. ', err); 
      throw new AppError(err, "dbError", "Unable to connect to the database or some error occurred while executing your query."); 
     }); 
} 
+0

あなたはどんなエラーがありましたか –

+0

私はCSVファイルをダウンロードするリクエストを生成するときに何のエラーも表示されません。その間、ファイルがダウンロードされるまで応答しません。何かがブロックされていることを意味します。 –

+0

それはループのためにイベントループをブロックしているため、クラスタまたは子プロセスの使用を試みることができます –

答えて

0

これはブロックしている:

for (var i = 0; i < 100000; i++) { //Testing purpose 
     for (var training of result) { 
      overDueTrainings.push({ 
       'Over Due Trainings': training.OverDueTrainings 
      }) 
     } 
    } 

を実行が終了するまで。

var result = reportManager.getOverdueTrainings(JSON.parse(req.params.criteria)); 
    result.then(function (result) { 
/****/ 
return await connection.executeQuerySequelize(sequelize, query, Sequelize.QueryTypes.RAW, replacements); 
+0

実際にブロックされていて、このループが実行されている間にnode.jsプロセス(ほかのイベントや要求を含む)の他のJavascriptは実行できないため、なぜこれが下降しているのか分かりません。 – jfriend00

+0

だから私はループの代わりにこれをテストできますか? –

+0

@ jfriend00ええ、なぜ、あなたは正しいのか分からない。 @ saad-zulfiqarあなたは本当にブロックするバックエンドにテスト 'blocking '部分を置くべきです –

0

NodeJSシングルスレッド、単一のプロセスです。 JavaScript関数が実行されている限り、それ以外は実行できません。これは設計によるものです。イベントループは、関数の実行が停止された後に再び開始されます。

+0

私は質問に関してあなたの答えを完全に否定しました。 node.jsには、そうするためのアプローチがたくさんあります。私はあなたが書いたものに同意しましたが。 –

+0

本当に質問はありませんでしたが、私はOPとして、なぜそれがブロックされているのかを質問しました。回避策にジャンプする前に、javascriptのイベントループを理解することが重要です。 – Evert

0

Node.jsはシングルスレッドで動作しています。したがって、非同期呼び出しを使用して小さなプロセスに使用する必要があります。 async/awaitを使用すると、コールバック関数がブロックされます。

したがって、データベース機能を有望なものとして使用する必要があります。非同期で動作します。

.query('CALL someFunction()') 
.then(function(response){ 
     //done 
    }).error(function(err){ 
    //error 
}); 

しかし、問題があります。結果を21回ロードする必要があります。したがってこの場合、再帰関数を使用する必要があります。再帰呼び出しを終了すると、非同期としてクライアントにデータを送信できます。

関連する問題