如何测试函数是否在Ember中返回一个promise?

Kev*_*hey 3 ember.js rsvp.js

在Ember中,我有时遇到需要检查函数是否返回promise的情况.例如,如果我有一个派生的路线:

MyRoute = ParentRoute.extend({
  beforeModel: function() {
    this._super().then(function() {
      // do something...
    });
  }
});
Run Code Online (Sandbox Code Playgroud)

但是虽然beforeModel可以返回一个承诺,但它可能不会.特别是,如果它是默认Ember.K实现,那么它不是.我宁愿不总是这样做:

var res = this._super();
if (typeof res.then === "function") {
  res.then(function() {
    // do X
  });
} else {
  // do X
}
Run Code Online (Sandbox Code Playgroud)

我假设有一种方法来包装一些人不知道的东西,如果它是一个可能的,然后链接无论如何.但我在文档中找不到它.

以上是不可取的,因为它很冗长,并且要求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'
Run Code Online (Sandbox Code Playgroud)

谢谢你的解决方案!似乎RSVP的Promises实现也有一个内置的解决方法,可以按照你的建议做,并且结果cast与你所建议的相同,但是现在已经弃用了.

小智 7

可能有其他更好的方法来做到这一点,但你可以这样做:

function ensurePromise(x) {
    return new Ember.RSVP.Promise(function(resolve) {
        resolve(x);
    });
}
Run Code Online (Sandbox Code Playgroud)

如果x不是一个承诺,那么这将返回一个已经用该值实现的承诺,然后您可以将其挂起then.如果x 承诺,则返回承诺,承诺其状态(包括已解决/拒绝状态和价值/原因).

这相当于本机Promises

Promise.resolve(x)
Run Code Online (Sandbox Code Playgroud)

所以在你的情况下,

MyRoute = ParentRoute.extend({
    beforeModel: function() {
        ensurePromise(this._super()).then(function() {
            // do something...
        });
    }
});
Run Code Online (Sandbox Code Playgroud)

但请注意,这可能会将同步值转换为异步值(promise).但是,通常认为在某些情况下具有同步行为而在其他情况下异步行为的函数是不好的做法.所以看起来似乎没问题,在这种情况下我们有一个可能是同步或者同步的值异步,将它强制转换成总是异步的东西.

我相信在过去的某些版本中曾经有过这样的东西RSVP.Promise.cast,我似乎记得这些东西大致相同,但我现在无法追踪它.