How do you chain queries in order using knex.js?

£可爱£侵袭症+ 提交于 2019-12-05 05:02:43

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

TL;DR: Do this:

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 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 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 won't work because the function you're passing in to then doesn't actually call add_default_user!

Flattening the Chain

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

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:**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())
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!