2015-09-03 27 views
6

Sto tentando di utilizzare una classe ES6 come servizio angolare ma quando viene creata un'istanza, i metodi non hanno accesso alle variabili del costruttore.Servizio angolare con classe ES6 e Babel

class dataWrapperService { 

    constructor($q, $log) { 
     this.$q = $q; 
     this.$log = $log; 
    } 

    data() { 
     console.log(this.$q); 
    } 
} 

dataWrapperService.$inject = ['$q', '$log']; 

app.service('dataWrapper', dataWrapperService); 

volta che il servizio viene iniettato da angolare e chiamo il metodo dati su di esso, il metodo non riesce ad avere accesso ai valori del costruttore.

// calling the data method results in an error 
dataWrapper.data(); //TypeError: Cannot read property '$q' of undefined 

// console.log output of dataWrapper: 
Object 
    $log: Object 
    $q: Q(resolver) 
    __proto__: smDataWrapperService 
    constructor: smDataWrapperService($q, $log) 
    data: data() 
    __proto__: Object 

MA ...

posso nuova il dataWrapperService manualmente e che funziona bene.

var dataWrapper = new smDataWrapperService("hello", "sir"); 
dataWrapper.data(); // "hello" 

Cosa mi manca qui?

UPDATE:


Ciò sembra accadere solo in callback promessa:

solito passare le funzioni di poi/catch come questo:

$http.get('whatever').then(dataWrapper.data); 

Ma solo quanto segue funzionerà:

$http.get('whatever').then((response) => smDataWrapper.data(response)) 

risposta

3

L'angolo ha bisogno di una funzione allo app.factory('dataWrapper', dataWrapperService); e non di una classe.

È possibile aggiungere un metodo di fabbrica statico alla classe e aggiungerlo a app.factory. (vedi aggiornamento sotto frammento di codice)

Il codice come questo dovrebbe funzionare:

class dataWrapperService { 

    constructor($q, $log) { 
     this.$q = $q; 
     this.$log = $log; 
    } 

    data() { 
     console.log(this.$q); 
    } 

    static dataWrapperFactory($q, $log) { 
     dataWrapperService.instance = new dataWrapperService($q, $log); 
     return dataWrapperService.instance; 
    } 
} 

dataWrapperService.$inject = ['$q', '$log']; 

app.factory('dataWrapper', dataWrapperService.dataWrapperFactory); 

Aggiornamento

Così come accennato nei commenti il ​​codice dovrebbe funzionare perché una classe ES6 è un costruttore funzione ed è quello che si aspetta angular.service.

Verificherò in seguito se riesco a vedere qualsiasi altro problema con il tuo codice.

+0

ho pensato che angular.service ha una funzione di costruzione e chiamato "nuovo" su di esso? – Failpunk

+0

Sì, mi dispiace, hai ragione. Il mio codice è per una fabbrica. Lo correggerò. Non so cosa c'è di sbagliato nel tuo codice. Ho visto molti esempi come nel tuo codice. – AWolf

+0

Sembra che questo accada solo con promesse. Aggiornato gli esempi sopra. – Failpunk

2

So che questo è in ritardo, ma forse qualcuno sarà inciampare su questo problema come me oggi con problemi simili, in modo da ...

In realtà, non si tratta di promesse. Quando si esegue questa operazione:

let function1 =() => {} 
let function2 = function1 

realtà, this oggetto è diverso per le funzioni. Pertanto, quando si prova .then(function1), in realtà function1 viene copiato nel parametro successCallback ed è this modificato.

Ma quando si utilizza .then(() => function1()), successCallback riceve il vostro lambda, e l'attuale this di function1 non tutto è perduto.

Quindi, se non si sa, quello che fai mai assegnare una funzione a una funzione in javascript, utilizzare lambda invece

+0

Se si desidera assegnare un metodo di classe di servizio a una funzione di controller, farlo come '$ scope.isLoggedIn =() => {Auth.isLoggedIn(); }; ', invece di' $ scope.isLoggedIn = Auth.isLoggedIn; '. Altrimenti il ​​'this' punterà al controller stesso e non alla classe. Grazie per l'apertura degli occhi. – arcol

+0

@arcol Ho passato qualche ora fa cercando di capirlo, felice di poter risparmiare a qualcuno questo dolore – SMSk

0

Con angolare 1.6.4, sto ottenendo l'errore quando sto cercando iniettare un servizio definito come una classe in alcuni controller.

non può chiamare una classe in funzione

Così, invece, voglio usare una funzione come un servizio. Per mantenerlo il più pulito possibile esporterei una funzione che restituisce immediatamente una classe anonima istanziata. E fai questo in un file separato e importa e usa quella funzione per creare il servizio in un altro file.

E poiché stai chiedendo di usare ES6 con Babel, usa lo babel-plugin-angularjs-annotate per inoperare in sicurezza le dipendenze aggiungendo '/* @ngInject */' sopra la funzione esportata.

I servizi di iniezione $q e $log o disponibili alla classe tramite chiusura. (Non c'è bisogno di passarli nel costruttore e assegnare a questo.)

// dataWrapperService.js 
/* @ngInject */ 
export const dataWrapperService = ($q, $log) => new class { 
    constructor() { 
    // do stuff 
    } 

    data() { 
    // $q available through closure 
    console.log($q) 
    } 
}() 

// in your.module.js 
import angular from 'angular' 

import { dataWrapperService } from './dataWrapperService' 

export const YourModule = angular 
    .module('yourmodule', []) 
    .factory('dataWrapper', dataWrapperService) 
    .name 
Problemi correlati