首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Knex.js多链式查询

Knex.js多链式查询
EN

Stack Overflow用户
提问于 2018-03-24 19:20:38
回答 1查看 7.4K关注 0票数 3

我目前正在使用express编写一个项目,并使用knex.js处理迁移和查询。

我仍然在尝试理解承诺的概念,以及如何使用knex运行多个查询。

下面的代码将一个新记录插入到我的数据库中,它位于我的Unit model文件中。

代码语言:javascript
复制
this.addUnit = function(unit_prefixV, unit_nameV, unit_descriptionV, profile_id) {
         return new Promise(function(resolve, reject) {
             knex.insert({ unit_prefix: unit_prefixV, unit_name: unit_nameV, unit_description: unit_descriptionV })
                .into('units').then(function(unit) {
                    resolve(unit)
                }).catch(function(error) {
                    reject(error)
                })
         })
    }

在我的routes.js文件中,我在post请求中调用它,如下所示:

代码语言:javascript
复制
app.post('/dashboard/unit/add', ensureAuthenticated, function(req, res) {
        let postErrors = []
        if (req.body.unit_name.trim() == "") {
            postErrors.push('Unit name cannot be empty.')
        }

        if (req.body.unit_prefix.trim() == "") {
            postErrors.push('Unit prefix cannot be empty.')
        }

        if (req.body.unit_description.trim() == "") {
            postErrors.push('Unit description cannot be empty.')
        }

        if (postErrors.length > 0) {
            res.render('addUnit', { errors: postErrors, user: req.user })
        } else {
            unitModel.addUnit(req.body.unit_prefix.trim(), req.body.unit_name.trim(), req.body.unit_description.trim(), req.session.passport.user.id).then(function(unit) {
                res.redirect('/dashboard')
            })
        }
    })

这成功地将一条新记录插入到我的units表中,但是,我希望使用匹配的profile_id从user表中选择用户id,然后将另一条记录插入到我的users_units表中。都在this.addUnit函数中。

作为参考,我的users表包括:

  • id
  • google_id

我的users_units表包括:

  • user_id
  • unit_id

我尝试链接查询,但它只执行初始的insert查询,而不执行其他查询。这是一个相当丑陋的尝试:

代码语言:javascript
复制
this.addUnit = function(unit_prefixV, unit_nameV, unit_descriptionV, profile_id) {
         return new Promise(function(resolve, reject) {
             knex.insert({ unit_prefix: unit_prefixV, unit_name: unit_nameV, unit_description: unit_descriptionV })
                .into('units').then(function(unit) {
                    knex('users').where({ "google_id": profile_id }).select('id').then(function(uid) {
                        knex.insert({ user_id: uid, unit_id: unit }).into('users_units').then(function(user_units) {
                            resolve(user_unit)
                        }).catch(function(error) {
                            reject(error)
                        })
                        resolve(uid)
                    })
                    console.log(unit)
                    resolve(unit)
                }).catch(function(error) {
                    reject(error)
                })
         })
    }

任何帮助都将不胜感激!

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-03-24 21:24:36

你就快到了。这里有几个简单的要点需要把握:

  • 承诺只能重获一次。
  • 无论如何,不需要明确的承诺,因为自然发生的承诺是可以返回的。
  • return在每个阶段都有一个承诺.
  • ..。直到最内部的阶段,其中返回的值是最终交付的结果。
  • 除非您想要注入您自己的自定义错误消息或采取补救措施,否则不需要对错误进行隐式处理。

在考虑了所有这些之后,你可能会写:

代码语言:javascript
复制
this.addUnit = function(unit_prefixV, unit_nameV, unit_descriptionV, profile_id) {
    return knex.insert({ 'unit_prefix':unit_prefixV, 'unit_name':unit_nameV, 'unit_description':unit_descriptionV }).into('units')
 // ^^^^^^
    .then(function(unit) {
        return knex('users').where({ 'google_id':profile_id }).select('id')
     // ^^^^^^
        .then(function(uid) {
            return knex.insert({ 'unit_id':unit, 'user_id':uid }).into('users_units')
         // ^^^^^^
            .then(function(user_units) {
                return { 'unit_id':unit, 'user_id':uid, 'user_units':user_units };
             // ^^^^^^
            });
        });
    });
}

如果调用方只对进程的成功/失败感兴趣,而对整个{ unit, uid, user_units }对象不感兴趣,则可以省略最内部的.then()

代码语言:javascript
复制
this.addUnit = function(unit_prefixV, unit_nameV, unit_descriptionV, profile_id) {
    return knex.insert({ 'unit_prefix':unit_prefixV, 'unit_name':unit_nameV, 'unit_description':unit_descriptionV }).into('units')
    .then(function(unit) {
        return knex('users').where({ 'google_id':profile_id }).select('id')
        .then(function(uid) {
            return knex.insert({ 'unit_id':unit, 'user_id':uid }).into('users_units');
        });
    });
}

.addUnit()返回的承诺仍将交付user_units,调用方可以使用或忽略该承诺。

这些解决方案(和其他解决方案)有一个主要的条件;像这样的多阶段更新查询应该真正包装在事务 --即允许回滚早期阶段的内容中。否则,失败部分可能会使数据库处于某种不确定的状态。这个答案和任何一个起点一样是一个很好的起点。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/49468889

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档