Я пытаюсь разработать систему в стеке MEAN, которая должна содержать модель карты, хранящуюся в моей БД.Эта модель должна иметь два уникальных поля: идентификатор объекта и код карты, которые будут представлять собой буквенно-цифровую строку длиной 8 символов.Моя схема похожа на:
var cardSchema = new Schema({
cod: {type: String, required: true, unique: true},
titular: {type: String, required: true, index: true},
balance: {type: Number, default: 500, min: 0, max: 500, required: true},
lastCredited: {type: Date, default: Date.now(), required: true}
})
А потом я создавал свои объекты, такие как:
cards.js: post create /
router.post('/create', function(req, res) {
let card = new Card()
card.cod = Card.generateCod()
card.credit()
if (/^[a-zA-Z\s]+$/.test(req.body.titular)) {
card.titular = req.body.titular.toUpperCase()
}
else{
res.status(406).send('Invalid name for titular')
return
}
card.save(function (err, result) {
if(err) res.status(406).send(err)
else res.status(200).send(result)
})
})
Мой статический метод generateCodотвечал за распространение случайного строкового кода на карточки:
cardSchema.statics.generateCod = function(){
let possible = "ABCDEFGHIJ0123456789"
let cod = ''
for (var i = 0; i < 8; i++) cod += possible.charAt(Math.floor(Math.random() * possible.length))
return cod
}
Однако, чтобы избежать дублирования кодов, я искал какой-нибудь способ проверить, использовался ли уже сгенерированный код, а затемв положительном случае я бы сгенерировал еще один и повторил процесс, в отрицательном случае я бы просто возвратил код.Решением, которое я нашел, было отправка запроса в БД с передачей моего кода в качестве параметра и проверкой длины ответа, если длина была равна 0, это означало, что код был уникальным.Пока все хорошо, проблема в том, что мой запрос происходит асинхронно с кодом, я не могу просто использовать цикл while или for, чтобы проверить, является ли код уникальным, и разорвать цикл, когда он есть, потому что разрыв не будетработа и цикл будет продолжаться вечно.Я на самом деле пробовал это так:
while(true){
for (var i = 0; i < 8; i++) cod += possible.charAt(Math.floor(Math.random() * possible.length))
Card.find({cod: cod}, function(err, result) {
if(result.length === 0) break
})
}
return cod
Я также пробовал:
while(true){
for (var i = 0; i < 8; i++) cod += possible.charAt(Math.floor(Math.random() * possible.length))
Card.find({cod: cod}, function(err, result) {
if(result.length === 0) return cod
})
}
И даже:
let unique = false
while(!unique){
for (var i = 0; i < 8; i++) cod += possible.charAt(Math.floor(Math.random() * possible.length))
Card.find({cod: cod}, function(err, result) {
if(result.length === 0) unique = true
})
}
return cod
Но, похоже, ни один из них не работает,петля всегда идет вечно.Я относительно новичок в бэкэндах узлов и чувствую, что что-то упустил.Кто-нибудь знает, как я могу разорвать внешний цикл от асинхронного обратного вызова?Или даже альтернативный способ избежать дубликатов?Буду благодарен за любую помощь!