您如何使用 knex.js 按顺序链接查询?
How do you chain queries in order using knex.js?
我在理解 Knex.js 中的承诺如何工作时遇到了一些麻烦(使用 Bluebird.js 作为承诺)。我正在尝试做一些非常简单的事情,按顺序一个接一个地执行不同的插入语句,但我一直无法让它工作。
这是我目前的代码,它是在 authentication_type table 上执行插入,然后在 user_table 上执行插入,然后在 user_table 上执行插入类别 table.
// Import database connection
var knex = require('./db-connection.js');
// Add a row to authentication_type table so that user's can be created
function add_authentication_type() {
return knex('authentication_type')
.insert({id: 1, name: 'Internal'})
}
// Add a 'default' user with nil uuid
// Anything added without a user must link back to this user
function add_default_user() {
return knex('user_table')
.insert({user_table_id: knex.raw('uuid_nil()'),
authentication_type: 1,
authentication_token: "default"})
}
// Add categories so that locations can be created
function add_categories() {
return knex('category')
.insert([
{name: "Hospital",
description: "Where people go to get healed"},
{name: "Police Dept",
description: "Where people go when there’s trouble"},
{name: "Fire Dept",
description: "Where all the fire trucks are"}])
}
// Run the functions in the necessary order to fit constraints
add_authentication_type()
.then(add_default_user()
.then(add_categories()))
我需要这些插入以正确的顺序发生,从上到下,这样我就不会违反我的数据库的约束。这就是我试图通过在每个调用的 .then() 部分中链接调用来对最后几行执行的操作。我认为这会使第一个查询发生,然后是第二个,然后是第三个,但情况似乎并非如此,因为当 运行 这段代码时我遇到了约束违规错误。
我一直在阅读 Knex 和 Bluebird 页面,但我就是无法理解它。使用 Knex 执行这种顺序查询的正确方法是什么?
knex 查询构建器只是 returns 一个承诺,所以这只是正确链接这些承诺的问题。
TL;DR: 这样做:
add_authentication_type()
.then(add_default_user)
.then(add_categories)
承诺链接
让您的代码正常工作的关键是理解这四行做不同的事情:
// A
.then(add_default_user)
// B
.then(() => add_default_user())
// C
.then(add_default_user())
// D
.then(() => add_default_user)
then
将在前面的承诺解析后调用作为参数传递给它的任何函数。在 A
中,它调用 add_default_user
,returns 是一个承诺。在 B
中,它调用了整个函数,它本身 returns 是一个承诺返回函数。在这两种情况下 ,then
调用一个最终 returns 承诺的函数,这就是您正确链接承诺的方式。
C
不会按预期工作,因为您没有将函数传递给 then
,而是函数调用的 结果 。由于 promise 与回调一样是异步的,因此 returns 未定义并立即调用该函数,而不是等待先前的 promise 解决。
D
将不起作用,因为您传递给 then
的函数实际上并未调用 add_default_user
!
压平链条
如果您不小心,可能会得到功能正常但可读性不佳的代码("promise hell" 类似于回调地狱)。
foo()
.then((fooResult) => bar(fooResult)
.then((barResult)=> qux(barResult)
.then((quxResult)=> baz(quxResult)
)
)
)
这可行,但不必要地混乱。如果函数传递给 then
returns 一个承诺,则第一个 then
调用可以跟进第二个调用。第一个 then 中的 promise 解析为的值将被传递给第二个 then 中的函数。这意味着上面可以展平为:
foo()
.then((fooResult) => bar(fooResult))
.then((barResult)=> qux(barResult))
.then((quxResult)=> baz(quxResult))
**PROTIP:**如果您对排队等候电话感到厌烦,您也可以使用 Promise.resolve()
来启动您的承诺链,如下所示:
Promise.resolve()
.then(() => knex('table1').del())
.then(() => knex('table2').del())
.then(() => knex('table3').del())
我在理解 Knex.js 中的承诺如何工作时遇到了一些麻烦(使用 Bluebird.js 作为承诺)。我正在尝试做一些非常简单的事情,按顺序一个接一个地执行不同的插入语句,但我一直无法让它工作。
这是我目前的代码,它是在 authentication_type table 上执行插入,然后在 user_table 上执行插入,然后在 user_table 上执行插入类别 table.
// Import database connection
var knex = require('./db-connection.js');
// Add a row to authentication_type table so that user's can be created
function add_authentication_type() {
return knex('authentication_type')
.insert({id: 1, name: 'Internal'})
}
// Add a 'default' user with nil uuid
// Anything added without a user must link back to this user
function add_default_user() {
return knex('user_table')
.insert({user_table_id: knex.raw('uuid_nil()'),
authentication_type: 1,
authentication_token: "default"})
}
// Add categories so that locations can be created
function add_categories() {
return knex('category')
.insert([
{name: "Hospital",
description: "Where people go to get healed"},
{name: "Police Dept",
description: "Where people go when there’s trouble"},
{name: "Fire Dept",
description: "Where all the fire trucks are"}])
}
// Run the functions in the necessary order to fit constraints
add_authentication_type()
.then(add_default_user()
.then(add_categories()))
我需要这些插入以正确的顺序发生,从上到下,这样我就不会违反我的数据库的约束。这就是我试图通过在每个调用的 .then() 部分中链接调用来对最后几行执行的操作。我认为这会使第一个查询发生,然后是第二个,然后是第三个,但情况似乎并非如此,因为当 运行 这段代码时我遇到了约束违规错误。
我一直在阅读 Knex 和 Bluebird 页面,但我就是无法理解它。使用 Knex 执行这种顺序查询的正确方法是什么?
knex 查询构建器只是 returns 一个承诺,所以这只是正确链接这些承诺的问题。
TL;DR: 这样做:
add_authentication_type()
.then(add_default_user)
.then(add_categories)
承诺链接
让您的代码正常工作的关键是理解这四行做不同的事情:
// A
.then(add_default_user)
// B
.then(() => add_default_user())
// C
.then(add_default_user())
// D
.then(() => add_default_user)
then
将在前面的承诺解析后调用作为参数传递给它的任何函数。在 A
中,它调用 add_default_user
,returns 是一个承诺。在 B
中,它调用了整个函数,它本身 returns 是一个承诺返回函数。在这两种情况下 ,then
调用一个最终 returns 承诺的函数,这就是您正确链接承诺的方式。
C
不会按预期工作,因为您没有将函数传递给 then
,而是函数调用的 结果 。由于 promise 与回调一样是异步的,因此 returns 未定义并立即调用该函数,而不是等待先前的 promise 解决。
D
将不起作用,因为您传递给 then
的函数实际上并未调用 add_default_user
!
压平链条
如果您不小心,可能会得到功能正常但可读性不佳的代码("promise hell" 类似于回调地狱)。
foo()
.then((fooResult) => bar(fooResult)
.then((barResult)=> qux(barResult)
.then((quxResult)=> baz(quxResult)
)
)
)
这可行,但不必要地混乱。如果函数传递给 then
returns 一个承诺,则第一个 then
调用可以跟进第二个调用。第一个 then 中的 promise 解析为的值将被传递给第二个 then 中的函数。这意味着上面可以展平为:
foo()
.then((fooResult) => bar(fooResult))
.then((barResult)=> qux(barResult))
.then((quxResult)=> baz(quxResult))
**PROTIP:**如果您对排队等候电话感到厌烦,您也可以使用 Promise.resolve()
来启动您的承诺链,如下所示:
Promise.resolve()
.then(() => knex('table1').del())
.then(() => knex('table2').del())
.then(() => knex('table3').del())