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

#javascript #node.js #postgresql #express

#javascript #node.js #postgresql #выразить

Вопрос:

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

Как следует из названия, это принято? Потому что в моей базе данных мне нужно выполнить обещание 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));
}
}
  

Комментарии:

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

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

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

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

Ответ №1:

Проблема может быть внутри .then(data => { части. Вы создаете там новое обещание, но не возвращаете его в другую цепочку. Может случиться так, что это обещание не будет выполнено, потому что обещание-оболочка не предпринимает попыток выполнить это, поскольку оно не возвращается.

Вы можете изменить свой код следующим образом:

 .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.log(res) /*prints undefined*/);
  

Блок { Promise.resolve(res.toUpperCase()); } создает обещание, но ничего не возвращается, это означает, что обещание не является дальнейшей цепочкой и не может быть разрешено.

Все в порядке, когда обещание возвращается, обещание переходит в цепочку:

 Promise.resolve('abc')
    .then(res => { return Promise.resolve(res.toUpperCase()); })
    .then(res => console.log(res) /*prints ABC*/);
  

.then(res => { return Promise.resolve(res.toUpperCase()); }) Можно было бы сократить, как .then(res => Promise.resolve(res.toUpperCase())) в этом случае.

РЕДАКТИРОВАТЬ: еще несколько объяснений цепочки обещаний.

Комментарии:

1. В этом случае они иногда разрешаются. Он использует then / catch для сбора данных, но commit не может быть разрешен

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

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

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

Ответ №2:

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

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

И я рекомендую прочитать о цепочке обещаний, например.это:https://javascript.info/promise-chaining

Ответ №3:

Если обещания не зависят друг от друга? это означает, что вам не нужна информация из первого обещания, прежде чем вы сможете получить второе, тогда да, вы можете связать их вместе.

 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.log(responses)
    })
    .catch(err => {
      console.error(error)
    })