如何通过迭代给定的数组来一个接一个地执行异步操作?到目前为止,我尝试了每个函数,但似乎并行执行它。
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分钟直到循环结束。
答案 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;
将Promise.delay()
替换为您的实际异步操作。 mapSeries()
返回的承诺将解析为根据项目的原始顺序排序的处理结果数组。