2014-10-03 3 views
0

С помощью someAPI в нем требуются учетные данные, которые я хотел бы назначить динамически в конструкторе. Затем я хотел бы использовать someAPI во всем классе. То есть в следующем примере someMethodUsingSomeAPI - вспомогательный метод, который я хотел бы вызвать из других методов в экземпляре B. Возможно ли это с Coffee/JavaScript? (Единственный способ, которым я могу заставить его работать, если я ставлю someMethodUsingSomeAPI внутри конструктора.)Объект класса, созданный из конструктора

SomeAPI = Npm.require 'someAPI' 

class B extends A 
    constructor: (options = {}) -> 
    unless @ instanceof B 
     return new B(options) 

    @config = JSON.parse(Assets.getText('config/' + options.username + '.json')) 

    @someAPI = new SomeAPI 
     consumer_key: @config.credentials.consumer.key 
     consumer_secret: @config.credentials.consumer.secret 
     access_token: @config.credentials.access.token 
     access_token_secret: @config.credentials.access.secret 

    someMethodUsingSomeAPI = Async.wrap((id, callback) -> 
    return @someAPI.get 'whatever/show', { 'id': id }, callback 
) 

    console.log someMethodUsingSomeAPI '123' # Error: Cannot call method 'get' of undefined 

Обновлен с предложением от saimeunt

... 

someMethodUsingSomeAPI = (id) -> 
    wrappedGet = Async.wrap(@someAPI, 'get') 
    wrappedGet 'whatever/show', { id: id } 

console.log someMethodUsingSomeAPI '123' # ReferenceError: someMethodUsingSomeAPI is not defined 

&

b = B('username') 
b.someMethodUsingSomeAPI '123' # Works! 

изменяющегося someMethodUsingSomeAPI: к someMethodUsingSomeAPI =

&

b = B('username') 
b.someMethodUsingSomeAPI '123' # TypeError: Object #<B> has no method 'someMethodUsingSomeAPI' 

(Это с Метеор 0.9.3.1)

UPDATE в попытке ПРОЯСНИТЬ

Here's a simplified version of the above, without any of the API stuff.

someMethod = works, someMethod: doesn't work

Я рад, что classInstance.someMethod работает при использовании:, но ДЕЙСТВИТЕЛЬНО хотел бы, чтобы он работал в реальном экземпляре.

+0

Зачем вам статическую переменную 'someAPI' за пределами вашего класса вместо свойства * экземпляра *? – Bergi

+0

Обратите внимание, что 'JSON.parse' принимает строку JSON, а не путь к файлу. – Bergi

+0

Да, извините. Просто удалил некоторые из них для краткости. Добавлено обратно. – jiku

ответ

0

Уверенный, вы можете прикрепить someAPI к вашему объекту класса. В coffeescript @ используется вместо this (как и в Javscript).

SomeAPI = require 'someAPI' 

class A extends B 
    constructor: (options = {}) -> 
    unless @ instanceof A 
     return new A(options) 

    @config = JSON.parse('config/' + options.username + '.json') 

    @someAPI = new SomeAPI 
     consumer_key: @config.credentials.consumer.key 
     consumer_secret: @config.credentials.consumer.secret 
     access_token: @config.credentials.access.token 
     access_token_secret: @config.credentials.access.secret 

    someMethodUsingSomeAPI: (id, callback) -> 
    return @someAPI.get 'whatever/show', { 'id': id }, callback 

Вы посмотрите на this SO question, объясняющую Javascript this, и его объем может. Как только вы это поймете, взгляните на то, как работают coffeescript's classes, и вы должны иметь ясность в использовании @.

+0

Спасибо. Я думаю, что я попытался это начать, прежде чем пытаться объявить someAPI за пределами конструктора и т. Д. Обновлено исходное сообщение, чтобы отразить то, что я делаю, но я все равно получаю ту же ошибку, то есть 'Не могу вызвать метод 'get' of undefined'. – jiku

0

Я думаю, что это то, что вы хотите:

someMethodUsingSomeAPI:function(id){ 
    var wrappedGet=Async.wrap(@someAPI,"get"); 
    return wrappedGet("whatever/show",{ 
    id:id 
    }); 
} 
+0

Это отлично работало для b.someMethodUsingSomeAPI, но если я не испортил CS, он не будет работать внутри экземпляра. Обновлен приведенный выше пример с результатами. – jiku

+0

Пожалуйста, удалите '=' в пользу ':' при определении новых свойств в объектном литерале, потому что, если вы этого не сделаете, это абсолютно БЕСПЛАТНО, и я не знаю, как CS не предупреждает вас об этом. А как насчет этих стимулов B без «нового»? Вы вызывали someMethodUsingSomeAPI, используя правильный синтаксис в других методах, то есть '@ someMethodUsingSomeAPI'? – saimeunt

+0

Хорошо. Я понятия не имею, почему, но используя = у меня фактически был 'console.log someMethodUsingSomeAPI '123'', если я помещаю оба внутри конструктора. B wit (out) новый, похоже, не имеет значения. Просто возвращает новый, если уже не экземпляр B, как указано в конструкторе. Если я делаю 'console.log @someMethodUsingSomeAPI '123'', я получаю' TypeError: Object # не имеет метода' someMethodUsingSomeAPI'' – jiku

0

Основываясь на упрощенном примере вы предоставили вот версия, которая должна соответствовать вашим требованиям:

class SomeClass 
    # Store the last created instance at the class level 
    lastInstance: null 

    constructor: (options = {}) -> 
    @someLastName = options.someLastName 
    # In constructor, the created instance is now the lastInstance 
    SomeClass.lastInstance = this 

# The helper method is not created in the class scope 
someMethod = (someFirstName) -> 
    "Hello " + someFirstName + " " + SomeClass.lastInstance.someLastName 

someClass = new SomeClass({ someLastName: 'Borgnine' }) 

alert someMethod 'Ernest' 

И here's a link to try it in a browser.

В принципе, поскольку вы ожидаете, что ваш хелпер-метод получит доступ к экземпляру класса, вам необходимо предложить ссылку на этот экземпляр, который хелпер может ссылаться в какой-то момент. Здесь я использую переменную класса для хранения последнего созданного экземпляра и вспомогательного доступа, который последний экземпляр при вызове.Это означает, что при создании многих экземпляров он будет выполняться следующим образом:

someClass = new SomeClass({ someLastName: 'Borgnine' }) 

alert someMethod 'Ernest' # Hello Ernest Borgnine 

someClass = new SomeClass({ someLastName: 'Doe' }) 

alert someMethod 'Boris' # Hello Boris Doe 
Смежные вопросы