如何适时使用异步和同步编程
how to use asynchronous and synchronous programming in right time
我是 javascript 异步编程的新手。我有两个电子邮件提供商 sendgrid 和 mailgun。我想用其中一个发送电子邮件,然后如果发生任何错误,请重新发送另一个电子邮件。最后,如果电子邮件发送成功,则保存到数据库并使用 json 对象进行响应。
这是我的代码:
if(req.query.provider== 'mailgun'){
console.log('sending with mailgun ...');
mailgun.messages().send(data, function (err, res) {
if(err){
fail = true;
console.log(`error in sending email with mailgun. error :${err}`)
} else {
console.log('email sent with mailgun')
fail = false;
}
});
}else if(req.query.provider == 'sendgrid'){
console.log('sending emial with sendgrid')
sendgrid.sendMail(data, function(err, res) {
if (err) {
console.log(`error in sending with sendgrid. error: ${err} + response : ${res}`)
fail = true
}
console.log(`email sent with sendgrid`)
fail = false
});
}
if(fail){
if(req.query.provider == 'mailgun'){
console.log('sending with sendgrid ...')
sendgrid.sendMail(data, function(err, res){
if(err){
console.log(`error: ${err} + response : ${res}`)
}else {
console.log(`response: ${res}`)
fail = false
}
})
}else if(req.query.provider == 'sendgrid'){
console.log('sendging with mailgun')
mailgun.messages().send(data, function (err, res) {
if(err){
console.log(`error: ${err} + response : ${res}`)
}else{
console.log(`response: ${res}`)
fail = false
}
})
}
}
if(!fail){
db.models.Email.create(req.query, (err, result)=>{
if(err){
handleErrors(res, err);
console.log(`error in creating Email :${err}`)
}else {
console.log()
res.json(result)
}
});
} else {
console.log('fail in sending error');
res.json('sorry.');
}
});
这里的问题是,这段代码 运行 是异步的。例如,它使用 mailgun 发送,然后跳转到失败检查并使用 sendgrid 再次发送。不等待发送的响应。
我该如何解决和改进这个问题?我应该使用 async',
await'?
您可以尝试 JavaScript 的延迟和承诺执行。请在没有延迟和承诺的情况下使用下面的第一个示例。在那之后,你会发现延迟和承诺执行是多么容易,
var firstData = null;
var secondData = null;
var responseCallback = function () {
if (!firstData || !secondData)
return;
// do something
}
$.get("http://example.com/first", function (data) {
firstData = data;
responseCallback();
});
$.get("http://example.com/second", function (data) {
secondData = data;
responseCallback();
})
Then the same with deferred and promise,
var firstPromise = $.get("http://example.com/first");
var secondPromise = $.get("http://example.com/second");
$.when(firstPromise, secondPromise).done(function (firstData, secondData) {
// do something
});
您可以在此处阅读更多内容 https://davidwalsh.name/write-javascript-promises
这里是一个使用 async/await 模式的例子
(可以改进以支持一般的多个邮件程序,您必须调整您 select alternativeMailerName 的部分).
/**
* Send an email using a given mailer
*
* return true if success, false otherwise
*/
async sendMailUsingMessages(mailerName, data) {
const {
mailer,
func,
} = [
{
mailer: 'mailgun',
func: async () => mailgun.messages().send(data);
},
{
mailer: 'sendgrid',
func: async () => sendgrid.sendMail(data);
},
].find(x => x.mailer === mailerName);
console.log(`sending with ${mailer} ...`);
try {
const res = await func();
console.log(`email sent with ${mailer}`);
return true;
} catch (err) {
console.log(`error in sending email with ${mailer}. error :${err}`)
return false;
}
}
/**
* Send an email
*/
async sendEmail(req, res, data) {
if (!(await sendMailUsingMessages(req.query.provider, data))) {
// One fail, so we try the other one
const alternativeMailerName = req.query.provider === 'mailgun' ? 'sendgrid' : 'mailgun';
if (!(await sendMailUsingMessages(alternativeMailerName, data))) {
// Double fail
console.log('fail in sending error');
res.json('sorry.');
return;
}
}
// Success
try {
const result = await db.models.Email.create(req.query);
res.json(result);
} catch (err) {
handleErrors(res, err);
console.log(`error in creating Email :${err}`)
}
}
我是 javascript 异步编程的新手。我有两个电子邮件提供商 sendgrid 和 mailgun。我想用其中一个发送电子邮件,然后如果发生任何错误,请重新发送另一个电子邮件。最后,如果电子邮件发送成功,则保存到数据库并使用 json 对象进行响应。 这是我的代码:
if(req.query.provider== 'mailgun'){
console.log('sending with mailgun ...');
mailgun.messages().send(data, function (err, res) {
if(err){
fail = true;
console.log(`error in sending email with mailgun. error :${err}`)
} else {
console.log('email sent with mailgun')
fail = false;
}
});
}else if(req.query.provider == 'sendgrid'){
console.log('sending emial with sendgrid')
sendgrid.sendMail(data, function(err, res) {
if (err) {
console.log(`error in sending with sendgrid. error: ${err} + response : ${res}`)
fail = true
}
console.log(`email sent with sendgrid`)
fail = false
});
}
if(fail){
if(req.query.provider == 'mailgun'){
console.log('sending with sendgrid ...')
sendgrid.sendMail(data, function(err, res){
if(err){
console.log(`error: ${err} + response : ${res}`)
}else {
console.log(`response: ${res}`)
fail = false
}
})
}else if(req.query.provider == 'sendgrid'){
console.log('sendging with mailgun')
mailgun.messages().send(data, function (err, res) {
if(err){
console.log(`error: ${err} + response : ${res}`)
}else{
console.log(`response: ${res}`)
fail = false
}
})
}
}
if(!fail){
db.models.Email.create(req.query, (err, result)=>{
if(err){
handleErrors(res, err);
console.log(`error in creating Email :${err}`)
}else {
console.log()
res.json(result)
}
});
} else {
console.log('fail in sending error');
res.json('sorry.');
}
});
这里的问题是,这段代码 运行 是异步的。例如,它使用 mailgun 发送,然后跳转到失败检查并使用 sendgrid 再次发送。不等待发送的响应。
我该如何解决和改进这个问题?我应该使用 async',
await'?
您可以尝试 JavaScript 的延迟和承诺执行。请在没有延迟和承诺的情况下使用下面的第一个示例。在那之后,你会发现延迟和承诺执行是多么容易,
var firstData = null;
var secondData = null;
var responseCallback = function () {
if (!firstData || !secondData)
return;
// do something
}
$.get("http://example.com/first", function (data) {
firstData = data;
responseCallback();
});
$.get("http://example.com/second", function (data) {
secondData = data;
responseCallback();
})
Then the same with deferred and promise,
var firstPromise = $.get("http://example.com/first");
var secondPromise = $.get("http://example.com/second");
$.when(firstPromise, secondPromise).done(function (firstData, secondData) {
// do something
});
您可以在此处阅读更多内容 https://davidwalsh.name/write-javascript-promises
这里是一个使用 async/await 模式的例子
(可以改进以支持一般的多个邮件程序,您必须调整您 select alternativeMailerName 的部分).
/**
* Send an email using a given mailer
*
* return true if success, false otherwise
*/
async sendMailUsingMessages(mailerName, data) {
const {
mailer,
func,
} = [
{
mailer: 'mailgun',
func: async () => mailgun.messages().send(data);
},
{
mailer: 'sendgrid',
func: async () => sendgrid.sendMail(data);
},
].find(x => x.mailer === mailerName);
console.log(`sending with ${mailer} ...`);
try {
const res = await func();
console.log(`email sent with ${mailer}`);
return true;
} catch (err) {
console.log(`error in sending email with ${mailer}. error :${err}`)
return false;
}
}
/**
* Send an email
*/
async sendEmail(req, res, data) {
if (!(await sendMailUsingMessages(req.query.provider, data))) {
// One fail, so we try the other one
const alternativeMailerName = req.query.provider === 'mailgun' ? 'sendgrid' : 'mailgun';
if (!(await sendMailUsingMessages(alternativeMailerName, data))) {
// Double fail
console.log('fail in sending error');
res.json('sorry.');
return;
}
}
// Success
try {
const result = await db.models.Email.create(req.query);
res.json(result);
} catch (err) {
handleErrors(res, err);
console.log(`error in creating Email :${err}`)
}
}