我目前正在使用express编写一个项目,并使用knex.js处理迁移和查询。
我仍然在尝试理解承诺的概念,以及如何使用knex运行多个查询。
下面的代码将一个新记录插入到我的数据库中,它位于我的Unit model文件中。
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请求中调用它,如下所示:
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表包括:
我的users_units表包括:
我尝试链接查询,但它只执行初始的insert查询,而不执行其他查询。这是一个相当丑陋的尝试:
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)
})
})
}任何帮助都将不胜感激!
发布于 2018-03-24 21:24:36
你就快到了。这里有几个简单的要点需要把握:
return在每个阶段都有一个承诺.在考虑了所有这些之后,你可能会写:
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():
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,调用方可以使用或忽略该承诺。
这些解决方案(和其他解决方案)有一个主要的条件;像这样的多阶段更新查询应该真正包装在事务 --即允许回滚早期阶段的内容中。否则,失败部分可能会使数据库处于某种不确定的状态。这个答案和任何一个起点一样是一个很好的起点。
https://stackoverflow.com/questions/49468889
复制相似问题