首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >A+承诺是否需要在调用`.then`之后执行副作用?

A+承诺是否需要在调用`.then`之后执行副作用?
EN

Stack Overflow用户
提问于 2016-08-02 21:34:10
回答 3查看 99关注 0票数 1

我被用于构建模式的Knex在调用.then之前不实际创建表的方式给绊倒了。

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

代码语言:javascript
运行
复制
knex.schema.createTable('users', table => {
  table.string('name')
})

但这段代码将:

代码语言:javascript
运行
复制
knex.schema.createTable('users', table => {
  table.string('name')
}).then(console.log.bind(console))

这种行为(在调用.then之前不做任何事情):

( a) 承诺A+规范的要求

( b) 承诺A+规范禁止的

( c)未指明

我看了规范,行为似乎没有具体说明,但我不确定。这似乎太重要了,不可能具体说明。

更新

请参见@Vohuman的回答: Knex模式构建器上的then方法首先执行一个副作用,然后返回一个承诺。因此,即使我的问题的答案是(b)康耐视不会违反规范。虽然选择then作为方法名在这种情况下是非常误导的。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2016-08-04 00:29:06

这并不完全是“错误的”,尽管它并不常见。Knex需要.then,因为它必须能够判断查询是什么时候完成的,而不是中间版本。

文档中的示例 (评注后加):

代码语言:javascript
运行
复制
knex.select('name').from('users')    
  .where('id', '>', 20)              // Can I issue the query yet?
  .andWhere('id', '<', 200)          // Okay I'll...oh, you have more conditions.
  .limit(10)                         // Hey, I'm here, still ready...
  .offset(x)                         // Just let me know when you want me to--
  .then(function(rows) {             // OH OKAY I'll issue it now.
    return _.pluck(rows, 'name');
  })

谷歌的API.js助手也遵循这个模式,特别适用于即时和批处理查询:

创建请求并将其添加到批处理时,请在请求添加到批处理后才调用其then方法。如果在添加请求之前调用then方法,则请求将立即发送,而不是作为批处理的一部分发送。

正如SLaks所指出的,在文档中的任何地方都没有显式地指定这一点:为了使对象符合承诺/A+,它必须有一个具有正确语义和返回值的then方法,而且没有任何东西指定then不能有额外的行为。当然,这禁止这些API库将then方法重命名为更贴切的方法,如thenIssueRequestthenGetResponse。(您可以添加别名,但then必须存在。)

作为API,唯一的选择是将承诺的创建与then的链接分开,但要注意的是,几乎每一个对then的调用都有一个额外的方法调用,在此之前或封装它。因为then是访问结果的唯一方法,所以我可以理解对普通情况的优化将如何导致删除额外的方法。

代码语言:javascript
运行
复制
fluentApi.createRequest().parameterA(1).parameterB(2).issue().then(...);
// or
fluentApi.issue(fluentApi.createRequest().parameterA(1).parameterB(2)).then(...);

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

代码语言:javascript
运行
复制
knex.schema.createTable('users', table => {
  table.string('name')
}).catch(console.log.bind(console));

如果您坚持跳过错误处理,那么甚至可以有一个空的...and。

代码语言:javascript
运行
复制
knex.schema.createTable('users', table => {
  table.string('name')
}).then(null);


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

Stack Overflow用户

发布于 2016-08-02 21:39:58

这种行为是错误的;调用then()不应该有超出承诺本身的任何副作用(即执行回调)。

然而,规范实际上并没有提到这一点。

票数 1
EN

Stack Overflow用户

发布于 2016-08-02 21:46:26

knex是一个查询生成器。then只是一个助手函数,它执行生成的SQL语句,并在幕后调用承诺对象的then函数。如果将then替换为.toString函数,则将得到生成的字符串。这里的then不是承诺对象的方法。

来自knex源代码:

代码语言:javascript
运行
复制
Target.prototype.then = function(/* onFulfilled, onRejected */) {
   const result = this.client.runner(this).run()
   return result.then.apply(result, arguments);
};
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/38730850

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档