与Promises串行执行操作

时间:2017-07-27 16:05:29

标签: promise

如何通过迭代给定的数组来一个接一个地执行异步操作?到目前为止,我尝试了每个函数,但似乎并行执行它。

var Sequelize = require('sequelize');
var _ = require('underscore');
var Promise = require("bluebird");
var dateFormat = require('dateformat');
const fs = require('fs');
Promise.promisifyAll(fs);
var scissors = require('scissors');

var socket = require('socket.io-client')("http://localhost:6001");
socket.on("connect", function(){
  console.log(socket.connected);
})


var sequelize = new Sequelize('ptls','root','ODYSSEY99GRANITE',{
  host: 'master.cegtagfijlyq.us-west-2.rds.amazonaws.com',
  dialect: 'mysql',
  logging: false
});

var Meters = require("./models/meters")(sequelize);
var Residents = require("./models/residents")(sequelize);
var Servers = require("./models/servers")(sequelize);
var Dials = require("./models/dials")(sequelize);
var Billings = require("./models/billings")(sequelize);
var FormulaRow = require("./models/formulaRow")(sequelize);
var Note = require("./models/note")(sequelize);
var resident_invoice_formula_row = require("./models/resident_invoice_formula_row")(sequelize);
var invoice = require('./modules/invoice');




Billings.hasMany(resident_invoice_formula_row,{foreignKey:"billing_id"});
resident_invoice_formula_row.belongsTo(Billings,{foreignKey:"billing_id"});

Residents.hasMany(resident_invoice_formula_row,{foreignKey:"resident_id"});
resident_invoice_formula_row.belongsTo(Residents,{foreignKey:"resident_id"});

FormulaRow.hasMany(resident_invoice_formula_row,{foreignKey:"formula_row_id"});
resident_invoice_formula_row.belongsTo(FormulaRow,{foreignKey:"formula_row_id"});

var billing_id = parseInt(process.argv.slice(2)[0]);
console.log("child process started with billing_id = " + billing_id);
var invoice_obj_arr = [];
var pdfs = [];
Residents.getCurrentResidentsByBillingId(billing_id)
.then(function(residents){
  residentsLoop = [];
  var i=0;
  _.each(residents,function(resident,index, sr){
    i++;
    var invoice_obj = {};
    invoice_obj.company_address = "1465 Pickering Parkway,Suite 100  Pickering, ON, L1V7G7             Local: 905-837-8548                     Toll Free: 1-866-836-3837  info@prioritymeter.com www.prioritymeter.com";
    invoice_obj.account_number = resident.resident_id;
    invoice_obj.name = resident.full_name;
    invoice_obj.address_line_1 = resident.mailing_address;
    invoice_obj.address_line_2 = resident.city + ", "+ resident.province;
    invoice_obj.address_line_3 = resident.postal_code;
    invoice_obj.service_address = resident.service_at;
    residentsLoop.push(
    Meters.getMetersByResidentId(resident.id)
      .then(function(meters){
        var metersLoop = [];
        _.each(meters, function(meter){
          metersLoop.push(
            Servers.getServerIdByMeterId(meter.id)
            .then(function(server_id){
            /*  if(index ==0){
                socket.emit("invoice_progress", {
                  "billing_id":billing_id,
                  "message":"Getting Name",
                  "progress": 20
                });
              }
              */
              return Meters.getNameByMeterId(meter.id)
              .then(function(name){
                /*
                if(index == 0){
                  socket.emit("invoice_progress", {
                    "billing_id":billing_id,
                    "message":"Getting Previous Total",
                    "progress": 30
                  });
                }
                */
                return Dials[server_id[0].server_id].getPreviousTotalByChannelServerAndSN(server_id[0].server_id,name[0].meter_id,billing_id)
                .then(function(previous_total){
                  /*
                  if (index == 0){
                    socket.emit("invoice_progress", {
                      "billing_id":billing_id,
                      "message":"Getting Current Total",
                      "progress": 40
                    });
                  }
                  */
                  return Dials[server_id[0].server_id].getCurrentTotalByChannelServerAndSN(server_id[0].server_id,name[0].meter_id,billing_id)
                  .then(function(current_total){
                    /*
                    if(index == 0){
                      socket.emit("invoice_progress", {
                        "billing_id":billing_id,
                        "message":"Getting Start Date",
                        "progress": 50
                      });
                    }
                    */
                    return Promise.all([Billings.getStartDateById(billing_id),Billings.getEndDateById(billing_id)])
                    .then(function(result){
                      var meter_obj = {
                        meter_no: meter.meter_id,
                        days: Math.round(Math.abs((result[0][0].start_date.getTime() - result[1][0].end_date.getTime())/(24*60*60*1000))),
                        prev_read_date: dateFormat(result[0][0].start_date, "mediumDate"),
                        current_read_date: dateFormat(result[1][0].end_date,"mediumDate"),
                        code:"MR",
                        current_reading:current_total[0].total,
                        prev_reading:previous_total[0].total,
                        multiplier: meter.multiplier,
                        usage:Math.round((current_total[0].total - previous_total[0].total)*meter.multiplier*100)/100
                      };
                      if (meter.type == 1)  meter_obj.meter_type = "EL";
                      else if (meter.type == 0) meter_obj.meter_type = "W";

                      if (meter.type == 1)  meter_obj.units = "KWh";
                      else if (meter.type ==0)   meter_obj.units = "m3";
                      return meter_obj;
                    })
                  })
                })
              })
            })
          )
        })
        return Promise.all(metersLoop);
      })
      .then(function(meter_array){
        invoice_obj.meters = meter_array;
        //sum of meter readings
        var meter_reading = 0;
        _.each(meter_array,function(meter){
          meter_reading += meter.usage;
        });
        /*
        if(index == 0){
          socket.emit("invoice_progress", {
            "billing_id":billing_id,
            "message":"Getting Charges",
            "progress": 60
          });
        }
        */

        return FormulaRow.getChargesByBillingId(billing_id)
        .then(function(charges){
          /*
          if(index == 0){
            socket.emit("invoice_progress", {
              "billing_id":billing_id,
              "message":"Getting Formula",
              "progress": 70
            });
          }
          */
          return FormulaRow.getFormulaCodeByBillingId(billing_id)
          .then(function(codes){
            var string_code = FormulaRow.concatFormulaCode(codes);
            var invoice_charges = [];
            var notes=[];
            _.each(charges,function(charge){
              var invoice_charge ={};
              var note = {};
              var value = parseFloat(Math.round(FormulaRow.evaluateValue(string_code,charge.item,meter_reading)*100)/100).toFixed(2);
              var title = FormulaRow.evaluateTitle(string_code,charge.description,meter_reading);
              if (FormulaRow.IsAmountDue(title)) invoice_obj.amount_due = "$"+value.toString();
              if (((value !=0) ||(charge.text != null))&&(charge.display != 1))
              {
                if(value >= 0){
                  invoice_charge.charge = "$"+value.toString();
                }
                else{
                  invoice_charge.charge = "($"+value.toString().substring(1)+")";
                }
                invoice_charge.title = title;
                invoice_charges.push(invoice_charge);
              }
              if ((value !=0)&&(charge.display == 1))
              {
                note.text = charge.text +" $"+value.toString();
                notes.push(note);
              }
              if ((charge.display != 1)&&(charge.text != null))
              {
                note.text = charge.text;
                notes.push(note);
              }
              charge.formula_row_id = charge.id;
              charge.resident_id = resident.id;
              charge.value = invoice_charge.charge;
              charge.title = invoice_charge.title;
              charge.billing_id = billing_id;
              delete charge.id;
              delete charge.item;
              delete charge.description;


            });
            invoice_obj.charges = invoice_charges;
            invoice_obj.notes = notes;
            return resident_invoice_formula_row.bulkCreate(charges, { individualHooks: true })
            .then(function(){
            });
          })
        });
      })
      .then(function(result){
        /*
        if(index == 0){
          socket.emit("invoice_progress", {
            "billing_id":billing_id,
            "message":"Getting Foot Notes",
            "progress":80
          });
        }
        */

        return Note.getFootNoteByBillingId(billing_id).then(function(note){

          /*
          if(index == 0){
            socket.emit("invoice_progress", {
              "billing_id":billing_id,
              "message":"Getting Messages",
              "progress": 90
            });
          }
          */

          return Note.getMessageByBillingId(billing_id).then(function(message){
/*
            if(index ==0){
              socket.emit("invoice_progress", {
                "billing_id":billing_id,
                "message":"Getting Billing Date",
                "progress": 100
              });
            }
            */
            return Billings.getBillingDateById(billing_id).then(function(billing){
              invoice_obj.statement_date = dateFormat(billing[0].billing_date, "mediumDate");
              invoice_obj.messages = _.map(note[0].text.split("\n"), function(text){return {"text":text.replace(/\'/g,"'") };});
              invoice_obj.side_messages = _.map(message[0].text.split("\n"), function(text){return {"text":text.replace(/\'/g,"'") };});
              pdfs.push(invoice_obj);
            });
          })
        });
      })
    );
  });
  Promise.each(residentsLoop,function(item,index,length){
    console.log(index);
    return item;
  })
  .then(function(residents_array){
    console.log("finish");
    if (!fs.existsSync("public/pdf/"+billing_id)) fs.mkdirSync("public/pdf/"+billing_id);
    invoice.get(pdfs, "public/pdf/"+billing_id+"/billing.pdf");
  })
});

我尝试了这段代码,但结果与预期的结果非常不同。

120异步操作的循环在2分钟内完成,所有突然的所有索引从0到119都被打印,然后打印完成。如果它是连续执行操作,它将打印0 - 等待1秒2然后等待一秒钟和3等待一秒钟并继续运行2分钟直到循环结束。

1 个答案:

答案 0 :(得分:1)

Promise在创建后立即开始执行。这意味着如果你有一系列的承诺,所有这些承诺已经开始了#34;。

但我想最初你有一个项目数组,你需要异步处理。并且您希望逐个处理这些项目,一次产生一个异步操作。

Promise.mapSeries()可以提供帮助:



const items = ["a", "b", "c", "d"];

Promise
    .mapSeries(items, (item, index) => {
        console.log(index, item);
        const delay = 500 - 100 * index;
        return Promise.delay(delay, item)
    })
    .then(() => console.log("done"));

<script src="https://cdn.jsdelivr.net/bluebird/latest/bluebird.js"></script>
&#13;
&#13;
&#13;

Promise.delay()替换为您的实际异步操作。 mapSeries()返回的承诺将解析为根据项目的原始顺序排序的处理结果数组。