nodejs – 帮助“promisifying”使用嵌套promise读取的文件

所以我最近钻研尝试了解承诺和背后的目的,由于JavaScript的asynchronous行为。 虽然我“理解”了我的理解,但我仍然在为如何促使某些东西返回未来价值而奋斗,然后执行新的代码块来做其他事情。 我使用的两个主要节点模块:

  • PG-承诺
  • exceljs

我想要做的是读取一个文件,然后一旦完全读取,迭代每个工作表执行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? }); 

但是当我在承诺中有一个承诺时,我感到非常困惑。我有db.tx调用,它本质上是一个嵌套在.eachSheet函数内的promise。 请帮助一个愚蠢的程序员理解! 在这一个上头撞墙。 🙂

如果我理解正确,你正试图链接承诺。

我build议你阅读Promises anti-pattern这篇伟大的文章 (参见“The Collection Kerfuffle”部分)

如果您需要执行系列承诺,则本文build议使用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(); }); }); } 

不要忘记包括承诺模块:

 var Promise = require('promise'); 

我没有testing我的代码,可能包含一些错字错误。