如何使用knex.js顺序链接查询? [英] How do you chain queries in order using knex.js?

查看:188
本文介绍了如何使用knex.js顺序链接查询?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在理解Knex.js中的诺言如何工作时遇到了一些麻烦(使用Bluebird.js来实现诺言).我正在尝试做一些非常简单的事情,依次执行不同的插入语句,但是我无法使其正常工作.

I'm having some trouble understanding how the promises in Knex.js work (uses Bluebird.js for promises). I'm trying to do something pretty simple, execute different insert statements one after another in order, but I haven't been able to get it to work.

这是我到目前为止的代码,用于在authentication_type表上执行插入操作,然后在user_table上执行插入操作,然后在category表上执行插入操作.

Here's the code I have so far, which is meant to execute an insert on the authentication_type table, then an insert on the user_table, and then an insert on the category 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()部分中链接调用来处理最后几行的内容.我以为这会使第一个查询发生,然后第二个查询,然后第三个查询,但是由于在运行此代码时遇到约束违规错误,所以情况似乎并非如此.

I need these inserts to happen in the correct order, from top to bottom, so I don't violate the constraints of my database. That's what I was attemping to do with the last few lines by chaining calls in the .then() portion of each call. I thought this would make the first query happen, then the second, then the third, but that doesn't appear to be the case since I get constraint violation errors when running this code.

我一直在阅读Knex和Bluebird页面,但我对此一无所知.用Knex执行这种顺序查询的正确方法是什么?

I've been reading through the Knex and Bluebird pages, but I just can't get a grasp on it. What is the proper way to go about executing this kind of sequential querying with Knex?

推荐答案

knex查询构建器仅返回一个Promise,因此这只是正确链接这些Promise的问题.

The knex query builder just returns a promise, so this is just a matter of correctly chaining those promises.

TL; DR:执行此操作:

add_authentication_type()
  .then(add_default_user)
  .then(add_categories)

承诺链

使代码正常工作的关键是理解以下四行代码可以做的不同的事情:

Promise Chaining

The key to getting your code to work is understanding these four lines do different things:

// 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,这将返回一个承诺.在B中,它将调用整个函数,该函数本身将返回一个promise-returning函数.在这两种情况下,then都会调用一个函数,该函数最终会返回一个Promise,这就是您正确链接Promise的方式.

then will call whatever function is passed as an argument to it after the preceding promise resolves. In A it calls add_default_user, which returns a promise. In B, it calls that entire function, which itself returns a promise-returning function. In both of these cases, then calls a function that eventually returns a promise, which is how you correctly chain promises.

C不会按预期方式工作,因为您没有将函数传递给 result 到then.因为promise与回调一样是异步的,所以它返回未定义的值,并且会立即调用该函数,而不是等待先前的promise解析.

C will not work as expected, because you're not passing a function to then, but the result of the function call. Because promises, like callbacks, are asynchronous, this returns undefined and also immediately calls that function, instead of waiting for the previous promise to resolve.

D将不起作用,因为您传递给then的函数实际上并未调用add_default_user

D won't work because the function you're passing in to then doesn't actually call add_default_user!

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

If you're not careful, you can end up with functional, but not exactly readable code (a "promise hell" similar to callback hell).

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

这有效,但不必要地混乱.如果传递给then的函数返回了Promise,则可以在第一个then调用之后进行第二个调用.然后将第一个中的promise解析为的值将传递给第二个中的函数.这意味着可以将以上内容简化为:

This works, but is unnecessarily messy. If the function passed to then returns a promise, the first then call can be followed up with a second one. The value the promise inside the first then resolves to will then be passed to the function inside the second then. That means the above can be flattened to:

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

** PROTIP:**如果您想排成一线,也可以使用Promise.resolve()这样的方式启动诺言链:

**PROTIP:**If you're anal about lining up your calls, you can also kick off your promise chain with a Promise.resolve() like this:

Promise.resolve()
  .then(() => knex('table1').del())
  .then(() => knex('table2').del())
  .then(() => knex('table3').del())

这篇关于如何使用knex.js顺序链接查询?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆