我如何测试一个函数是否在 Ember 中返回一个承诺?
How can I test if a function is returning a promise in Ember?
在 Ember 中,我有时会 运行 遇到需要检查函数是否 return 的情况。例如,如果我有一条派生路线:
MyRoute = ParentRoute.extend({
beforeModel: function() {
this._super().then(function() {
// do something...
});
}
});
但是虽然 beforeModel 可以 return 一个承诺,但它可能不会。特别是,如果它是默认的 Ember.K
实现,则不会。我宁愿不要总是做:
var res = this._super();
if (typeof res.then === "function") {
res.then(function() {
// do X
});
} else {
// do X
}
我假设有一种方法可以包装一些人们不知道它是否可用的东西,然后不管它是否链接。但是我在文档中找不到它。
以上内容不受欢迎,因为它冗长,并且需要两次 X 的代码。
想法?
更新:
我能够通过以下 coffeescript 测试确认@torazaburo 的回应:
`import { test, module } from 'ember-qunit'`
module "testing promise behavior"
test "can cast to promise", ->
expect 3
order = []
returnsPromise = ->
new Ember.RSVP.Promise (resolve) ->
order.push 'a'
resolve('response 1')
returnsValue = ->
order.push 'b'
'response 2'
Ember.run ->
Ember.RSVP.resolve(returnsPromise()).then (response) ->
order.push 'c'
equal response, 'response 1'
Ember.RSVP.resolve(returnsValue()).then (response) ->
order.push 'd'
equal response, 'response 2'
equal order.join(' '), 'a b c d'
感谢解答!似乎 RSVP 的 Promises 实现也有一个内置的 resolve 方法来执行你的建议,结果与你建议的 cast
相同,尽管现在已弃用。
可能还有其他更好的方法,但您可以这样做:
function ensurePromise(x) {
return new Ember.RSVP.Promise(function(resolve) {
resolve(x);
});
}
如果 x
不是一个承诺,那么这个 returns 一个已经用那个值实现的承诺,然后你可以挂起 then
。如果 x
是 一个承诺,那么它 returns 一个假定其状态的承诺(包括 resolved/rejected 状态和 value/reason)。
这在原生 Promise 中等同于
Promise.resolve(x)
所以在你的情况下,
MyRoute = ParentRoute.extend({
beforeModel: function() {
ensurePromise(this._super()).then(function() {
// do something...
});
}
});
但是请注意,这可能会将同步值转换为异步值(承诺)。但是,通常认为函数在某些情况下同步运行而在其他情况下运行异步被认为是不好的做法。所以看起来没问题,如果我们有一个可能是同步 或 异步的值,将其强制转换为始终异步的值。
我相信在过去的某个版本中曾经有一个叫做 RSVP.Promise.cast
的东西,我记得它做了大致相同的事情,但我现在找不到它了。
在 Ember 中,我有时会 运行 遇到需要检查函数是否 return 的情况。例如,如果我有一条派生路线:
MyRoute = ParentRoute.extend({
beforeModel: function() {
this._super().then(function() {
// do something...
});
}
});
但是虽然 beforeModel 可以 return 一个承诺,但它可能不会。特别是,如果它是默认的 Ember.K
实现,则不会。我宁愿不要总是做:
var res = this._super();
if (typeof res.then === "function") {
res.then(function() {
// do X
});
} else {
// do X
}
我假设有一种方法可以包装一些人们不知道它是否可用的东西,然后不管它是否链接。但是我在文档中找不到它。
以上内容不受欢迎,因为它冗长,并且需要两次 X 的代码。
想法?
更新:
我能够通过以下 coffeescript 测试确认@torazaburo 的回应:
`import { test, module } from 'ember-qunit'`
module "testing promise behavior"
test "can cast to promise", ->
expect 3
order = []
returnsPromise = ->
new Ember.RSVP.Promise (resolve) ->
order.push 'a'
resolve('response 1')
returnsValue = ->
order.push 'b'
'response 2'
Ember.run ->
Ember.RSVP.resolve(returnsPromise()).then (response) ->
order.push 'c'
equal response, 'response 1'
Ember.RSVP.resolve(returnsValue()).then (response) ->
order.push 'd'
equal response, 'response 2'
equal order.join(' '), 'a b c d'
感谢解答!似乎 RSVP 的 Promises 实现也有一个内置的 resolve 方法来执行你的建议,结果与你建议的 cast
相同,尽管现在已弃用。
可能还有其他更好的方法,但您可以这样做:
function ensurePromise(x) {
return new Ember.RSVP.Promise(function(resolve) {
resolve(x);
});
}
如果 x
不是一个承诺,那么这个 returns 一个已经用那个值实现的承诺,然后你可以挂起 then
。如果 x
是 一个承诺,那么它 returns 一个假定其状态的承诺(包括 resolved/rejected 状态和 value/reason)。
这在原生 Promise 中等同于
Promise.resolve(x)
所以在你的情况下,
MyRoute = ParentRoute.extend({
beforeModel: function() {
ensurePromise(this._super()).then(function() {
// do something...
});
}
});
但是请注意,这可能会将同步值转换为异步值(承诺)。但是,通常认为函数在某些情况下同步运行而在其他情况下运行异步被认为是不好的做法。所以看起来没问题,如果我们有一个可能是同步 或 异步的值,将其强制转换为始终异步的值。
我相信在过去的某个版本中曾经有一个叫做 RSVP.Promise.cast
的东西,我记得它做了大致相同的事情,但我现在找不到它了。