2015-12-20 23 views
6

Chcę utworzyć obiekt w JavaScript.Uzyskiwanie dostępu do "tego" obiektu wewnątrz wywołania zwrotnego obietnicy (wtedy)

Jedna z metod powinna wykonać łańcuch obietnic. Każda z metod w łańcuchu musi uzyskać dostęp do zmiennej konfiguracyjnej, która jest członkiem obiektu. Problem polega na tym, że operator this został zmieniony w PromiseMethod2 i nie mogę uzyskać dostępu do zmiennej konfiguracyjnej (działa poprawnie w PromiseMethod1).

Oto mój kod:

var SomeObject(config) { 
    var that = this; 
    that.config = config; 
} 

SomeObject.prototype.SomeMethod = function() { 
    var that = this; 

    that.PromiseMethod1() 
     .then(that.PromiseMethod2) 
     .catch(console.error); 
    } 

SomeObject.prototype.PromiseMethod1 = function() { 
    var that = this; 
    config = that.config; 

    return SomePromise(); 
} 

SomeObject.prototype.PromiseMethod2 = function(someParams) { 
    var that = this; 
    config = that.config; 
    params = someParams; 

    return SomePromise(); 
} 


var someObject = new SomeObject(someConfig); 
someObject.SomeMethod().then(function() { 
    console.log('Done!'); 
} 

chcę użyć delegata metoda w sieci, a nie tylko wykonanie:

that.PromiseMethod1().then(function(response) { return that.PromiseMethod2(that, response); }; 

nie mogę użyć metody bind bo wygląda na to zostanie ponownie powiązana, gdy wywołanie zwrotne zostanie wykonane.

Czy istnieje rozwiązanie tego problemu? Dlaczego istnieje różnica między PromiseMethod1 a PromiseMethod2?

+0

Jak rozpoznajesz 'SomePromise'? – Kiril

+0

Każda metoda może działać inaczej. Przeważnie używam "nowej obietnicy (rozwiązać, odrzucić)", a następnie rozwiązać (niektórePramy). Lub korzystam z obietnicy innej firmy, takiej jak ElasticSearch lub Request-Promise – shudima

+0

Potwierdzasz, że nie możesz używać bindów, ale czy próbowałeś? Wygląda na to, że to właściwe rozwiązanie. –

Odpowiedz

1

Moja prawdziwy zalecenie jest nie do korzystania w ogóle z this lub new (można również użyć Object.create, jeśli nadal chcesz dziedziczyć):

var SomeObject = function(config) { 
    return { 
     PromiseMethod1: function(){ 
      return somePromise(config.foo); 
     }, 
     PromiseMethod2: function(x){ 
      return someOtherPromise(config.bar, x); 
     } 
    } 
} 

var instance = SomeObject({config: true}); 
instance.PromiseMethod1().then(instance.PromiseMethod2); 

Tutaj używam zamknięć, a ich zdolność do dołączania zmiennych ich macierzystego zakresu leksykalnego, na moją korzyść. Zamiast polegać na JavaScriptu, aby magicznie wstrzyknąć this do mojej funkcji w czasie wykonywania w oparciu o obiekt, do którego funkcja jest wywoływana, ponieważ jak pokazuje twój problem, to nie zawsze działa.

Wiem jednak, że jego niekonwencjonalny sposób do pracy, więc jeśli wolisz trzymać this, trzeba użyć bind aby powiedzieć JavaScript, która magiczne this -value funkcji należącej do:

var SomeObject function(config) { 
    this.config = config; 
} 

SomeObject.prototype.PromiseMethod1 = function(){ 
    return somePromise(this.config.foo); 
} 

SomeObject.prototype.PromiseMethod1 = function(x){ 
    return someOtherPromise(this.config.bar, x); 
} 

var instance = new SomeObject({config: true}); 
instance.PromiseMethod1().then(instance.PromiseMethod2.bind(instance)); //<- :(

W twoim przykładzie SomeMethod w rzeczywistości nie używasz bind. Nadal musisz wiązać, ponieważ przekazujesz funkcję do .then(f), a kod, który odbiera tę funkcję, nie wie już, który obiekt powinien być użyty w celu uzyskania this. Teraz spójrz na mój wcześniej zalecany kod ponownie.Nie ma tam żadnych funkcji, więc te funkcje w ogóle nie polegają na obiekcie, do którego są wywoływane, możesz je przekazać jako funkcje wyższego rzędu, ile chcesz, bez konieczności wcześniejszego bind lub that = this . :)

0

Powiedziałbym, że to niemożliwe. Próbujesz połączyć 2 różne podejścia: method chaining i promises chaining. Polecam przejrzeć Twoją architekturę.

Jedyną widoczną rzeczą (ale osobiście mi się to nie podoba), jeśli masz pełną kontrolę nad wszystkimi obietnicami, których chcesz użyć, jest przekazanie wartości konfiguracyjnych przez cały łańcuch obietnic.

SomeObject.prototype.init = function() { 
    var that = this; 

    return new Promise(function(resolve, reject) { 
     resolve(that.config) 
    }); 
} 
SomeObject.prototype.PromiseMethod1 = function(config, params) { 
    return SomePromise(config, params); 
} 

SomeObject.prototype.PromiseMethod2 = function(config, someParams) { 
    return SomePromise(config, someParams); 
} 

SomePromise = function(config, params) { 
    return new Promise(function(resolve, reject) { 
     //some code here 
     resolve(config, newParamsFromSomeCode) 
    }); 
} 

Wtedy będziesz mógł zadzwonić:

that.init().then(that.PromiseMethod1).then(that.PromiseMethod2); 

Ale znowu, to nie wygląda jak dobry kod ...

+0

Nie ma metody łączenia. wszystkie metody są w SomeObject. Próbowałem tego podejścia, problem polega na tym, że metoda Obietnica nie obsługuje więcej niż 1 argumentu. – shudima

+0

Tak, ale chcesz wywołać metody tego samego obiektu jeden po drugim. Jeśli naprawdę potrzebujesz kodu asynchronicznego - poleciłbym umieścić twoje operacje asynchroniczne w oddzielnych obiektach/warstwach/komponentach/cokolwiek i użyć prostego łączenia łańcuchów. – Kiril

Powiązane problemy