Я учусь использовать MongoDB, создав простое приложение для блога. Однако часть моего кода, которая сохраняет данное сообщение, кажется, иногда дает проблемы с обещаниями, но не всегда, и успешность кода просто кажется удачей.
Каждый пост в моей базе данных хранится с следующая схема:
{
title: String,
author: String,
body: String,
slug: String,
baseSlug: String,
published: { type: Boolean, default: false }
}
slug
определяет ссылку, используемую для доступа к сообщению в блоге, и автоматически создается на основе заголовка сообщения в блоге. Однако, если заголовки статей дублируются, к slug
будет добавлен номер в конце, чтобы отличить его от похожих статей, а baseSlug
останется прежним. Например:
- Я создаю сообщение
"My first post"
, и ему присваивается baseSlug
из "my-first-post"
. Поскольку никакие другие сообщения не имеют такого же baseSlug
, для slug
также установлено значение "my-first-post"
. - Я создаю еще одно сообщение с именем
"My first post"
, и ему присваивается baseSlug
из "my-first-post"
. Однако, поскольку другой пост имеет такой же baseSlug
, ему назначается slug
"my-first-post-1"
.
Чтобы создать такое поведение, я написал следующий маршрут addpost
в Express:
app.post("/addpost", (req, res) => {
let postInfo = req.body;
for (key of Object.keys(postInfo)) {
if (postInfo[key] == "true") postInfo[key] = true;
}
let slug = postInfo.title
.toLowerCase()
.split(" ")
.filter(hasNumber) // return /\d/.test(str);
.slice(0, 5)
.join("-");
postInfo.slug = slug;
var postData;
Post.find({ baseSlug: postInfo.slug }, (error, documents) => {
if (documents.length > 0) {
let largestSlugSuffix = 0;
for (let document of documents) {
var fullSlug = document.slug.split("-");
var suffix = fullSlug[fullSlug.length - 1];
if (!isNaN(suffix)) {
if (parseInt(suffix) > largestSlugSuffix) {
largestSlugSuffix = suffix;
}
}
}
largestSlugSuffix++;
postInfo.baseSlug = postInfo.slug;
postInfo.slug += "-" + largestSlugSuffix;
} else {
postInfo.baseSlug = postInfo.slug;
}
postData = new Post(postInfo);
})
.then(() => {
postData
.save()
.then(result => {
res.redirect("/");
})
.catch(err => {
console.log(err);
res.status(400).send("Unable to save data");
});
})
.catch(err => {
console.log(err);
res.status(400).send("Unable to save data");
});
});
Этот код, кажется, работает большую часть времени, но иногда он дает сбой и выводит следующее:
TypeError: Cannot read property 'save' of undefined
at C:\Users\User\BlogTest\app.js:94:18
at processTicksAndRejections (internal/process/task_queues.js:94:5)
(Для справки, строка 94 в моем файле - postData.save()
)
Я подозреваю, что это связано с тем, что выполнение основной части функции занимает больше времени, чем должно, а переменная postData
еще не определена. Однако postData.save()
не следует выполнять до завершения обещания из-за функции обратного вызова .then()
.
Почему мой код ведет себя так? Есть ли способ исправить?