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

时间:2017-10-06 22:27:13

标签: 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()))

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

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

1 个答案:

答案 0 :(得分:8)

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

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)
在先前的promise解析之后,

then将调用作为参数传递给它的任何函数。在A中,它会调用add_default_user,它会返回一个承诺。在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)
      )
    )
  )

这有效,但不必要地混乱。如果传递给then的函数返回一个promise,则第一个then调用可以跟进第二个foo() .then((fooResult) => bar(fooResult)) .then((barResult)=> qux(barResult)) .then((quxResult)=> baz(quxResult)) 调用。然后,第一个中的promise所解析的值将被传递给第二个中的函数。这意味着以上内容可以扁平化为:

Promise.resolve()

** PROTIP:**如果你唠叨排队通话,你也可以用这样的Promise.resolve() .then(() => knex('table1').del()) .then(() => knex('table2').del()) .then(() => knex('table3').del()) 启动你的承诺链:

import pandas as pd
data = pd.read_csv('my_file.csv')
data.head() #returns the first 5 rows of the dataframe
data.shape  # displays the # of rows and # of columns of dataframe