我有以下代码:
"use strict";
const Raven = require("raven");
Raven.config(
"test"
).install();
module.exports = function(Reservation) {
function dateValidator(err) {
if (this.startDate >= this.endDate) {
err();
}
}
function sendEmail(campground) {
return new Promise((resolve, reject) => {
Reservation.app.models.Email.send(formEmailObject(campground),
function(
err,
mail
) {
if (err) {
console.log(err);
Raven.captureException(err);
reject(err);
} else {
console.log(mail);
console.log("email sent!");
resolve(mail);
}
});
});
}
function formEmailObject(campground) {
return {
to: "loopbackintern@yopmail.com",
from: "noreply@optis.be",
subject: "Thank you for your reservation at " + campground.name,
html:
"<p>We confirm your reservation for <strong>" +
campground.name +
"</strong></p>"
};
}
Reservation.validate("startDate", dateValidator, {
message: "endDate should be after startDate"
});
Reservation.observe("after save", async function(ctx, next) {
try {
const campground = await Reservation.app.models.Campground.findById(
ctx.instance.campgroundId
);
const mail = await sendEmail(campground);
next();
} catch (e) {
Raven.captureException(e);
next(e);
}
});
};
抱歉格式不佳。当流程完成后,我收到此错误:
(node:3907) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): Error: Callback was already called.
我在两个地方调用next()回调,一个在try代码中,另一个在catch代码中。我假设当一切正常时,下一个回调只被调用一次,并且当它出错时也是如此。但它似乎被称为两次,我不知道为什么。
我还尝试在try / catch代码之外调用next,但它会导致相同的错误。如果我只留下在catch代码中调用的下一个,它就不会抛出错误。
有什么想法吗?谢谢!
答案 0 :(得分:1)
如果您使用的是异步功能,则不应明确调用下一个,会自动调用。
查看此github issue以获取loopback async / await
所以你的钩子可能如下所示。
Reservation.observe("after save", async ctx => {
try {
const campground = await Reservation.app.models.Campground.findById(
ctx.instance.campgroundId
);
const mail = await sendEmail(campground);
} catch (e) {
Raven.captureException(e);
throw e;
}
});
注意:除非你想修改/使用错误,否则你不需要将它包装在try catch中。
答案 1 :(得分:0)
您应该将sendEmail方法声明为async,因为它返回一个promise。
async function sendEmail(campground){ ... }
答案 2 :(得分:0)
在阅读this article之后,我创建了一个包含以下代码的await-handler.js文件。
module.exports = (promise) =>
promise
.then(data => ({
ok: true,
data
}))
.catch(error =>
Promise.resolve({
ok: false,
error
})
);
然后在MyModel.js文件中,我创建了一个异步函数来从数据库中获取值,如下所示。
const awaitHandler = require("./../await-handler.js")
const getMaxNumber = async (MyModel) => {
let result = await awaitHandler(MyModel.find());
if (result.ok) {
if (result.data.length) {
return result.data.reduce((max, b) => Math.max(max, b.propertyName), result.data[0] && result.data[0].propertyName);
} else {
return 0;
}
} else {
return result.error;
}
}
根据@ Mehari的回答,我已经评论了对next()
方法的调用,如下所示: -
module.exports = function(MyModel) {
MyModel.observe('before save', async(ctx, next) => {
const maxNumber = await getMaxNumber (MyModel);
if(ctx.instance) {
...
set the required property using ctx.instance.*
like createdAt, createdBy properties
...
// return next();
} else {
...
code for patch
...
// return next();
}
})
}
这解决了触发保存端点时的警告问题。
但是当我运行端点来加载资源时,仍会出现警告问题。喜欢
http://localhost:3000/api/MyModel
以前,只有在触发before save
操作挂钩时才会出现此问题。
遇到此问题后,我检查了添加access
和loaded
操作挂钩,我发现警告是在loaded
操作挂钩后发出的。
MyModel.observe('access', (ctx, next) => {
return next();
})
MyModel.observe('loaded', (ctx, next) => {
return next();
})
可能导致此问题的原因以及如何解决?