如何使用knex.js按顺序链接查询?

Sea*_*yer 7 javascript node.js knex.js

我在理解Knex.js中的承诺如何工作(使用Bluebird.js作为承诺)时遇到了一些麻烦.我正在尝试做一些非常简单的事情,按顺序依次执行不同的插入语句,但我无法让它工作.

这是我到目前为止的代码,它意味着在authentication_type表上执行插入,然后在user_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()))
Run Code Online (Sandbox Code Playgroud)

我需要从上到下以正确的顺序发生这些插入,所以我不违反我的数据库的约束.这就是我在最后几行中通过在每次调用的.then()部分中链接调用来尝试做的事情.我认为这会使第一个查询发生,然后是第二个,然后是第三个,但这似乎并非如此,因为我在运行此代码时遇到约束违规错误.

我一直在阅读Knex和Bluebird页面,但我无法掌握它.使用Knex执行此类顺序查询的正确方法是什么?

Dan*_*den 9

knex查询构建器只返回一个promise,所以这只是正确链接这些promise.

TL; DR:这样做:

add_authentication_type()
  .then(add_default_user)
  .then(add_categories)
Run Code Online (Sandbox Code Playgroud)

承诺链接

让代码工作的关键是理解这四行做不同的事情:

// A
.then(add_default_user)
// B
.then(() => add_default_user())
// C
.then(add_default_user())
// D
.then(() => add_default_user)
Run Code Online (Sandbox Code Playgroud)

then在前面的promise解析之后,将调用任何函数作为参数传递给它.在A它的调用中add_default_user,它返回一个promise.在B,它调用整个函数,它本身返回一个promise-returns函数.在这两种情况下,then调用最终返回promise的函数,这就是您正确链接promise的方式.

C将无法按预期工作,因为您没有传递函数then,而是函数调用的结果.因为promises(如回调)是异步的,所以返回undefined并立即调用该函数,而不是等待先前的promise来解析.

D将无法正常工作,因为您传入的功能then实际上并没有调用add_default_user!

扁平化链条

如果你不小心,你可能会得到功能性但不完全可读的代码(一个类似于回调地狱的"承诺地狱").

foo()
  .then((fooResult) => bar(fooResult)
    .then((barResult)=> qux(barResult)
      .then((quxResult)=> baz(quxResult)
      )
    )
  )
Run Code Online (Sandbox Code Playgroud)

这有效,但不必要地混乱.如果传递的函数then返回一个promise,则第一个then调用可以跟随第二个调用.然后,第一个中的promise所解析的值将被传递给第二个中的函数.这意味着以上内容可以扁平化为:

foo()
  .then((fooResult) => bar(fooResult))
  .then((barResult)=> qux(barResult))
  .then((quxResult)=> baz(quxResult))
Run Code Online (Sandbox Code Playgroud)

**PROTIP:**如果你是关于排队电话的肛门,你也可以用以下方式启动你的承诺链Promise.resolve():

Promise.resolve()
  .then(() => knex('table1').del())
  .then(() => knex('table2').del())
  .then(() => knex('table3').del())
Run Code Online (Sandbox Code Playgroud)