Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/node.js/37.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 通过knex迁移承诺所有种族条件_Javascript_Node.js_Race Condition_Knex.js - Fatal编程技术网

Javascript 通过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

有人告诉我,没有人能保证承诺的顺序。所有人都能解决承诺。然而,我看不出它并没有按照顺序解决

因此,以下knex迁移方法不应该工作,因为
消息
引用了用户表

然而,在几次迁移中,我从来没有遇到过一次出现竞争条件错误的实例。意思是,它看起来像承诺。所有根据索引位置解决

所以,我的问题是:下面的代码片段是否容易出现竞争条件

    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')};
。为了简洁起见,我在这里只列出了我许下的众多承诺中的一个。谢谢你的解释。