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

我在理解Knex.js中承诺的工作方面遇到了一些麻烦(使用Bluebird.js作为承诺)。 我试图做一些非常简单的事情,依次执行不同的插入语句,但是我一直无法使它工作。

这里是我到目前为止的代码,这是为了在authentication_type表上执行一个insert,然后在user_table上插入一个insert,然后在category表上插入一个insert。

// 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查询生成器只是返回一个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) 

then在前面的诺言解决之后,将调用作为parameter passing的任何函数。 在它调用add_default_user ,它返回一个承诺。 在B ,它调用了整个函数,它本身返回一个承诺函数。 在这两种情况下, then调用一个函数,最终返回一个承诺,这就是你如何正确链接承诺。

C不能按预期工作,因为你没有传递函数,而是函数调用的结果 。 因为承诺,如callback,是asynchronous的,这将返回未定义,并立即调用该函数,而不是等待以前的承诺解决。

D将无法正常工作,因为传入的函数实际上并没有调用add_default_user

展平链条

如果你不小心,你可以结束function,但不是完全可读的代码(类似于callback地狱的“承诺地狱”)。

 foo() .then((fooResult) => bar(fooResult) .then((barResult)=> qux(barResult) .then((quxResult)=> baz(quxResult) ) ) ) 

这工作,但不必要的混乱。 如果传递的函数返回一个promise,那么第一个调用可以跟在第二个之后。 那么第一个内部的值然后将解决的值传递给第二个内部的函数。 这意味着上面可以被平化为:

 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())