Javascript 承诺是A+;在`之后执行副作用所需的承诺。然后调用`?

Javascript 承诺是A+;在`之后执行副作用所需的承诺。然后调用`?,javascript,promise,Javascript,Promise,在你调用之后,才创建表,这让我大吃一惊 例如,此代码实际上不会影响数据库: knex.schema.createTable('users', table => { table.string('name') }) 但这一准则将: knex.schema.createTable('users', table => { table.string('name') }).then(console.log.bind(console)) 这是一种行为(在调用之前不执行任何操作): a)

在你调用
之后,
才创建表,这让我大吃一惊

例如,此代码实际上不会影响数据库:

knex.schema.createTable('users', table => {
  table.string('name')
})
但这一准则将:

knex.schema.createTable('users', table => {
  table.string('name')
}).then(console.log.bind(console))
这是一种行为(在调用
之前不执行任何操作):

a) 要求

b) 禁止

c) 未指明

?

我看了说明书,似乎行为没有说明,但我不确定。这似乎太重要了,不能不说明

更新
请参阅@Vohuman的答案:Knex schema builder上的
then
方法首先执行副作用,然后返回承诺。因此,即使我的问题的答案是(b)Knex不会违反规范。尽管在这种情况下选择
然后
作为方法名称是非常误导的。

这种行为是错误的;调用
then()


然而,规范实际上并没有对此做任何说明。

这种行为是错误的;调用
then()


然而,规范实际上并没有对此做任何说明。

knex
是一个查询生成器
then
只是一个助手函数,它执行生成的[SQL]语句,并在后台调用promise对象的
then
函数。如果用
.toString
函数替换
,则会得到生成的字符串<代码>然后
这里不是承诺对象的方法

knex
源代码:

Target.prototype.then = function(/* onFulfilled, onRejected */) {
   const result = this.client.runner(this).run()
   return result.then.apply(result, arguments);
};

knex
是一个查询生成器
then
只是一个助手函数,它执行生成的[SQL]语句,并在后台调用promise对象的
then
函数。如果用
.toString
函数替换
,则会得到生成的字符串<代码>然后
这里不是承诺对象的方法

knex
源代码:

Target.prototype.then = function(/* onFulfilled, onRejected */) {
   const result = this.client.runner(this).run()
   return result.then.apply(result, arguments);
};
这并不完全是“错误的”,尽管这并不常见。Knex需要
。然后
,因为它必须能够判断何时完成查询,而不是中期构建

(添加评注):


最后,请记住,您应该始终
在某个时刻捕捉到一个承诺,这将触发请求:

knex.schema.createTable('users', table => {
  table.string('name')
}).catch(console.log.bind(console));
…因此,如果您坚持跳过错误处理,您甚至可以有一个空的
,然后

knex.schema.createTable('users', table => {
  table.string('name')
}).then(null);


knex.schema.createTable('users', table => {
  table.string('name')
}).then();
这并不完全是“错误的”,尽管这并不常见。Knex需要
。然后
,因为它必须能够判断何时完成查询,而不是中期构建

(添加评注):


最后,请记住,您应该始终
在某个时刻捕捉到一个承诺,这将触发请求:

knex.schema.createTable('users', table => {
  table.string('name')
}).catch(console.log.bind(console));
…因此,如果您坚持跳过错误处理,您甚至可以有一个空的
,然后

knex.schema.createTable('users', table => {
  table.string('name')
}).then(null);


knex.schema.createTable('users', table => {
  table.string('name')
}).then();

根据协议,架构生成器确实返回了一个承诺。另外,您引用的代码中的函数返回一个承诺:
result
runner.run()
的返回值,它返回一个蓝鸟承诺。看见你能编辑你的答案吗?@mheiber这正是我想说的。
then
函数本身不是promise对象的方法,而是返回一个promise对象。那么,knex提供的
.then()
方法不是promise处理程序,这只是一个可怕的设计选择。奇怪的误导应该被命名为
.exec()
,以避免这种类型的混淆。@Vohuman,我明白了,谢谢你的解释。因此,Knex文档中的模式生成器返回承诺是正确的,但是,正如您所指出的,Knex在返回承诺之前也会执行一个副作用。因此,我关于规范合规性的问题与本例无关。非常有用。@jfriend00好吧,我同意它可能会误导人,但它使API更加简洁。例如,您可以编写
Promise.all([knex('table').truncate(),knex('other_table').insert({…})])
并将实例强制为Promise对象。根据。另外,您引用的代码中的函数返回一个承诺:
result
runner.run()
的返回值,它返回一个蓝鸟承诺。看见你能编辑你的答案吗?@mheiber这正是我想说的。
then
函数本身不是promise对象的方法,而是返回一个promise对象。那么,knex提供的
.then()
方法不是promise处理程序,这只是一个可怕的设计选择。奇怪的误导应该被命名为
.exec()
,以避免这种类型的混淆。@Vohuman,我明白了,谢谢你的解释。因此,Knex文档中的模式生成器返回承诺是正确的,但是,正如您所指出的,Knex在返回承诺之前也会执行一个副作用。因此,我关于规范合规性的问题与本例无关。非常有用。@jfriend00好吧,我同意它可能会误导人,但它使API更加简洁。例如,您可以编写
Promise.all([knex('table').truncate(),knex('other_table').insert({…})])
,实例被强制为Promise对象。我同意
then()
除了调用实现回调之外还有副作用是不对的,但是这种直觉有什么依据吗?我同意除了调用实现回调外,
then()
还有其他副作用是错误的,但是这种直觉有什么依据吗?A+规范没有明确说明,但这种对象被称为惰性承诺。关于同化算法是否允许懒惰,曾进行过一些讨论。A+规范未对其进行说明,但此类对象是已知的