我很难理解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执行这种顺序查询的正确方法是什么?
答案 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