我被用于构建模式的Knex在调用.then
之前不实际创建表的方式给绊倒了。
例如,这段代码实际上不会影响数据库:
knex.schema.createTable('users', table => {
table.string('name')
})
但这段代码将:
knex.schema.createTable('users', table => {
table.string('name')
}).then(console.log.bind(console))
这种行为(在调用.then
之前不做任何事情):
( a) 承诺A+规范的要求
( b) 承诺A+规范禁止的
( c)未指明
我看了规范,行为似乎没有具体说明,但我不确定。这似乎太重要了,不可能具体说明。
更新
请参见@Vohuman的回答: Knex模式构建器上的then
方法首先执行一个副作用,然后返回一个承诺。因此,即使我的问题的答案是(b)康耐视不会违反规范。虽然选择then
作为方法名在这种情况下是非常误导的。
发布于 2016-08-04 00:29:06
这并不完全是“错误的”,尽管它并不常见。Knex需要.then
,因为它必须能够判断查询是什么时候完成的,而不是中间版本。
文档中的示例 (评注后加):
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
方法重命名为更贴切的方法,如thenIssueRequest
或thenGetResponse
。(您可以添加别名,但then
必须存在。)
作为API,唯一的选择是将承诺的创建与then
的链接分开,但要注意的是,几乎每一个对then
的调用都有一个额外的方法调用,在此之前或封装它。因为then
是访问结果的唯一方法,所以我可以理解对普通情况的优化将如何导致删除额外的方法。
fluentApi.createRequest().parameterA(1).parameterB(2).issue().then(...);
// or
fluentApi.issue(fluentApi.createRequest().parameterA(1).parameterB(2)).then(...);
最后,请记住,您应该始终在某个时候catch
一个承诺,这将触发请求:
knex.schema.createTable('users', table => {
table.string('name')
}).catch(console.log.bind(console));
如果您坚持跳过错误处理,那么甚至可以有一个空的...and。
knex.schema.createTable('users', table => {
table.string('name')
}).then(null);
knex.schema.createTable('users', table => {
table.string('name')
}).then();
发布于 2016-08-02 21:39:58
这种行为是错误的;调用then()
不应该有超出承诺本身的任何副作用(即执行回调)。
然而,规范实际上并没有提到这一点。
发布于 2016-08-02 21:46:26
knex
是一个查询生成器。then
只是一个助手函数,它执行生成的SQL语句,并在幕后调用承诺对象的then
函数。如果将then
替换为.toString
函数,则将得到生成的字符串。这里的then
不是承诺对象的方法。
来自knex
源代码:
Target.prototype.then = function(/* onFulfilled, onRejected */) {
const result = this.client.runner(this).run()
return result.then.apply(result, arguments);
};
https://stackoverflow.com/questions/38730850
复制相似问题