Цепочка обещаний Javascript — это принято?

Меня беспокоит мой код, хотя он работает.

Как следует из названия, это принято? Потому что в моей базе данных мне нужно выполнить обещание 1, прежде чем переходить к обещанию 2, потому что мне нужно получить доступ к переменным и результатам обещания 1.

Итак, вкратце, что происходит в моей базе данных:

  1. Вставьте в: user_tbl затем
  2. Вставить в: login_tbl

Обратите внимание, что в 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));
}
}

Вы можете использовать async/await, чтобы сделать его более чистым и простым в обслуживании.

Code Maniac 14.03.2019 09:32

Это не принято, рекомендуется абсолютно. Обещания в основном были созданы, чтобы избежать проблемы ад обратного звонка, и это именно то, что у вас есть.

Cristian Traìna 14.03.2019 09:34

Нет ничего плохого в цепочке промисов, они предназначены для такой работы, пока вам нужно. Просто помните, чтобы избежать распространенных ошибок (поиск по JavaScript обещает ад, слишком много статей, чтобы выбрать одну для ссылки здесь).

Lewis 14.03.2019 09:37

Вы не связываете обещания, вы погружаетесь в них.

bato3 14.03.2019 09:45
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
0
4
60
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ответ принят как подходящий

Проблема может быть внутри части .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 14.03.2019 09:49

@bato3 bato3 Я новичок в обещаниях. Итак, могу я спросить, как commit не может быть решен?

Ardi 14.03.2019 09:55

@Арди, я ошибаюсь. Они решены. (существуют экзистенциальные проблемы, связанные с плохим утром)

bato3 14.03.2019 10:30
then функция оборачивает возвращаемое значение в обещание, если значение уже является обещанием, оно будет сглажено. Promise.resolve(true).then(res => Promise.resolve(res)) такое же, как Promise.resolve(true).then(res => res). Я редактирую свой ответ для дальнейшего объяснения.
ttulka 14.03.2019 11:00

Чтобы сделать это цепочкой, ваш код должен выглядеть примерно так:

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)
    })

Другие вопросы по теме