Javascript 通过knex迁移承诺所有种族条件
有人告诉我,没有人能保证承诺的顺序。所有人都能解决承诺。然而,我看不出它并没有按照顺序解决 因此,以下knex迁移方法不应该工作,因为Javascript 通过knex迁移承诺所有种族条件,javascript,node.js,race-condition,knex.js,Javascript,Node.js,Race Condition,Knex.js,有人告诉我,没有人能保证承诺的顺序。所有人都能解决承诺。然而,我看不出它并没有按照顺序解决 因此,以下knex迁移方法不应该工作,因为消息引用了用户表 然而,在几次迁移中,我从来没有遇到过一次出现竞争条件错误的实例。意思是,它看起来像承诺。所有根据索引位置解决 所以,我的问题是:下面的代码片段是否容易出现竞争条件 return Promise.all([ knex.schema.createTable('users', function(table) { ta
消息
引用了用户表
然而,在几次迁移中,我从来没有遇到过一次出现竞争条件错误的实例。意思是,它看起来像承诺。所有根据索引位置解决
所以,我的问题是:下面的代码片段是否容易出现竞争条件
return Promise.all([
knex.schema.createTable('users', function(table) {
table.increments().primary();
...
}),
knex.schema.createTable('messages', function(table) {
table.increments().primary();
table.bigInteger('user_id').unsigned().index()
.references('id').inTable('users');
}),
这是更好的方法吗
return Promise.all([
knex.schema.createTable('users', function(table) {
table.increments().primary();
...
}),
]).then(function() {
return Promise.all([
knex.schema.createTable('messages', function(table) {
table.increments().primary();
table.bigInteger('user_id').unsigned().index()
.references('id').inTable('users');
}),
});
})
由于您有一个依赖项,即您需要先创建第一个表,然后才能在第二个表中引用它,因此您应该使用
然后的方式
无论是否Promise.all
都将看到其promises按索引顺序解析,这与Promise无关。all
本身,而是作为参数传递给它的单个承诺。虽然您可以期望JavaScript(而不是Promise.all
)按顺序计算参数列表,但一般来说,您无法知道哪些承诺将首先解析。这是由这些单独的承诺决定的,而不是由承诺决定的
在您的例子中,这些单独的承诺做了类似的事情,即创建一个表,并且您的数据库引擎可能会按顺序处理这些语句,而没有并发性,实际上您可能会看到这些承诺总是按照您列出它们的顺序进行解析,但依赖这些承诺是不好的做法
请注意,如果您将一个数组中只有一个promise传递给promise.all
,您只需跳过该promise.all
,然后将立即应用于该单个promise。我希望此代码位于迁移文件中,默认情况下,迁移文件会创建隐式事务。因此,由于查询被发送到同一个连接,因此它们不会被并行解析
在这种情况下,数据库驱动程序(至少pg
)实际上会缓冲第二个查询,并等待第一个查询得到解决,然后再将第二个查询发送到数据库服务器
唯一重要的是这两个查询的执行顺序和发送给pg驱动程序的顺序
由于Promise.all
并不保证它会在knex.schema.createTable('users',…)
查询knex.schema.createTable('messages',…)
之前执行
tl;dr第一种方法不容易出现竞争条件,但如果查询以错误的顺序执行,它可能会失败。第二种方法更好。您不需要使用Promise。所有都在第二个代码段中。假设这些是XHR调用,它们将在您退出函数范围后立即启动。这意味着XHR请求将并发运行。这可能是因为您运气好,请求的顺序正按照您希望的方式完成,但是如果createTable('users')
需要在createTable('messages')
之前执行,那么您应该使用.then()
:knex.schema.createTable('users',…)。然后(()=>{knex.schema.createTable('messages')};
。为了简洁起见,我在这里只列出了我许下的众多承诺中的一个。谢谢你的解释。