Меня беспокоит мой код, хотя он работает.
Как следует из названия, это принято? Потому что в моей базе данных мне нужно выполнить обещание 1, прежде чем переходить к обещанию 2, потому что мне нужно получить доступ к переменным и результатам обещания 1.
Итак, вкратце, что происходит в моей базе данных:
Обратите внимание, что в login_tbl есть столбец, который является внешним ключом user_tbl. Поэтому я должен сначала закончить вставку в user_tbl, иначе будет ошибка.
Кстати, я использую postgresql, knex.js и bcrypt. Вот мой код:
//This is the function that handles the signup
const handleSignup = (req, res, db, bcrypt) => {
const { employeeId, username, password, firstName, lastName, positionSelect } = req.body;
const hash = bcrypt.hashSync(password);
if (!employeeId || !username || !password || !firstName || !lastName || !positionSelect) {
res.json({
haveEmpty: true
})
}
else{
db.transaction((trx) => {
db.select('*').from('user').where('employee_id', '=', employeeId)
.then(data => {
if (!data[0]){
db('user')
.returning('*')
.insert({
employee_id: employeeId,
username: username,
first_name: firstName,
last_name: lastName,
status: "Active",
position_id: positionSelect
})
.then(user =>{
db('login')
.returning('*')
.insert({
employee_id: employeeId,
username: username,
hash: hash
})
.then(login => {
if (login[0]){
res.json({
isSuccess: true
})
}else{
res.json({
isSuccess: false
})
}
})
.then(trx.commit)
.catch(trx.rollback);
})
.then(trx.commit)
.catch(trx.rollback);
}
else {
res.json('User already Exist!')
}
})
.then(trx.commit)
.catch(trx.rollback);
})
.catch(err => console.error(err));
}
}
Это не принято, рекомендуется абсолютно. Обещания в основном были созданы, чтобы избежать проблемы ад обратного звонка, и это именно то, что у вас есть.
Нет ничего плохого в цепочке промисов, они предназначены для такой работы, пока вам нужно. Просто помните, чтобы избежать распространенных ошибок (поиск по JavaScript обещает ад, слишком много статей, чтобы выбрать одну для ссылки здесь).
Вы не связываете обещания, вы погружаетесь в них.



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Проблема может быть внутри части .then(data => {. Вы создаете там новый Promise, но не возвращаете его в другую цепочку. Могло случиться так, что это обещание не будет разрешено, потому что обещание-оболочка не пытается это сделать, поскольку оно не возвращается.
Вы можете изменить свой код следующим образом:
.then(data => {
if (!data[0]){
return db('user')
а также
.then(user =>{
return db('login')
Если есть обещание, созданное и не возвращенное, следующий then ничего не получит:
Promise.resolve('abc')
.then(res => { Promise.resolve(res.toUpperCase()); })
.then(res => console.info(res) /*prints undefined*/);
Блок { Promise.resolve(res.toUpperCase()); } создает промис, но ничего не возвращается, значит промис не является дальнейшей цепочкой и не может быть разрешен.
Все нормально, при возврате промиса промис идет в цепочку:
Promise.resolve('abc')
.then(res => { return Promise.resolve(res.toUpperCase()); })
.then(res => console.info(res) /*prints ABC*/);
В этом случае .then(res => { return Promise.resolve(res.toUpperCase()); }) можно было бы сократить до .then(res => Promise.resolve(res.toUpperCase())).
Обновлено: еще одно объяснение цепочки промисов.
В этом случае они иногда разрешаются. Он использует then / catch для получения данных, но commit не может быть разрешен
@bato3 bato3 Я новичок в обещаниях. Итак, могу я спросить, как commit не может быть решен?
@Арди, я ошибаюсь. Они решены. (существуют экзистенциальные проблемы, связанные с плохим утром)
then функция оборачивает возвращаемое значение в обещание, если значение уже является обещанием, оно будет сглажено. Promise.resolve(true).then(res => Promise.resolve(res)) такое же, как Promise.resolve(true).then(res => res). Я редактирую свой ответ для дальнейшего объяснения.
Чтобы сделать это цепочкой, ваш код должен выглядеть примерно так:
db.transaction((trx) => {
return db.select('*').from('user').where('employee_id', '=', employeeId).then(data =>{
if (data[0]) {
res.json('User already Exist!')
//if it's possible use `return` instead `else`
return null;
}
return db('user')
.returning('*')
.insert({
employee_id: employeeId,
username: username,
first_name: firstName,
last_name: lastName,
status: "Active",
position_id: positionSelect
}).then(user=>{
return db('login')
.returning('*')
.insert({
employee_id: employeeId,
username: username,
hash: hash
})
}).then(login =>{
if (login[0]){
res.json({
isSuccess: true
})
}else{
res.json({
isSuccess: false
})
}
return true
}).then(trx.commit)
.catch(trx.rollback)
})
}).catch(err=> {
console.error(err)
res.status(500).json({error: true})
})
И я рекомендую прочитать о цепочке Promises, например, это: https://javascript.info/обещание-цепочка
Если обещания не зависят друг от друга? это означает, что вам не нужна информация из первого обещания, прежде чем вы сможете получить второе, тогда да, вы можете связать их вместе.
const Promise1 = fetch('https://API_URL_1');
const Promise2 = fetch('https:/API_URL_2');
Promise
.all([Promise1,Promise2])
.then(responses => {
return Promise.all(responses.map(res => res.json()))
})
.then(responses => {
console.info(responses)
})
.catch(err => {
console.error(error)
})
Вы можете использовать async/await, чтобы сделать его более чистым и простым в обслуживании.