मैं आयनिक 3/कोणीय 4 में निर्भरता इंजेक्शन के साथ किसी अन्य सेवा (घटक में नहीं) के भीतर एक सेवा का सरल उपयोग करने की कोशिश कर रहा हूं। मुझे लगा कि सैद्धांतिक रूप से मुझे समझ में आ गया है कि इसे कैसे करना है, लेकिन व्यवहार में मैं कई दिनों से संघर्ष कर रहा हूं ...

यहाँ मेरी विन्यास है:

cli packages:
    @ionic/cli-plugin-ionic-angular : 1.4.1
    @ionic/cli-utils                : 1.7.0
    ionic (Ionic CLI)               : 3.7.0
local packages:
    @ionic/app-scripts : 2.1.3
    Ionic Framework    : ionic-angular 3.6.0

और यह मेरी tsconfig.json फ़ाइल है (जैसा कि मैंने कुछ सूत्र पढ़े हैं जो सुझाव देते हैं कि संकलन विकल्प इंजेक्शन व्यवहार पर कुछ प्रभाव डाल सकते हैं)

{
  "compilerOptions": {
    "allowSyntheticDefaultImports": true,
    "declaration": false,
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "lib": [
      "dom",
      "es2015"
    ],
    "module": "es2015",
    "moduleResolution": "node",
    "sourceMap": true,
    "target": "es5"
  },
  "include": [
    "src/**/*.ts"
  ],
  "exclude": [
    "node_modules"
  ],
  "compileOnSave": false,
  "atom": {
    "rewriteTsconfig": false
  }
}

मेरे app.module.ts में, मैंने कुछ सेवाओं को उनके संबद्ध मॉड्यूल आयात करके पंजीकृत किया है: NgLoggerModule और IonicStorageModule, अन्य उन्हें प्रदाताओं में जोड़कर सरणी: सेटिंग्सस्टोरेजप्रोवाइडर और TMDbApiProvider:

@NgModule({
....
imports: [
    IonicStorageModule.forRoot(),
    NgLoggerModule.forRoot(Level.LOG)
],
providers: [
    ....
    SettingsStorageProvider,
    TMDbApiProvider
]

यह मेरी सेटिंग्सस्टोरेजप्रोवाइडर क्लास है जहां मैं बिना किसी समस्या के स्टोरेज और लॉगर सेवाओं का उपयोग कर सकता हूं:

@Injectable()
export class SettingsStorageProvider {

    constructor(public storage: Storage, public logger: Logger) {
        this.logger.log('Hello SettingsStorageProvider');
    }

    public saveSettings(_settings: SettingsModel){
    .... }

    public loadSettings(): Promise<SettingsModel> {
    ....}
}

यह मेरा TMDbApiProvider वर्ग है जहां मैं इंजेक्शन सेवाओं का उपयोग नहीं कर सकता लकड़हारा या सेटिंग्सस्टोरेजप्रोवाइडर यहां तक ​​​​कि सोचा कि वे ऐप में सही ढंग से पंजीकृत हैं .module.ts :

@Injectable()
export class TMDbApiProvider {

static get parameters() {
    return [[Http]];
}
    constructor(public settingsStorage: SettingsStorageProvider, public http: Http, 
    public logger: Logger) {
     if (settingsStorage == null)
         console.log('TMDbApiProvider:constructor-->settingsStorage is NULL !!!');
     if (logger  == null)
         console.log('TMDbApiProvider:constructor-->logger is NULL !!!');
     if (http == null)
         console.log('TMDbApiProvider:constructor-->http is NULL !!!');
}

    searchMovies(movieName) {
        this.settingsStorage.loadSettings().then((_settings) => {
        .....
            var url = Config.data.tmdb_searchService + encodeURI(movieName) + '&'+Config.data.tmdb_apiKey+'&'+Config.data.tmdb_language+_userSettings.getLanguage();
            var response = this.http.get(url).map(res => res.json());

            return response;
        });
    }
}

मुझे संकलन समय पर कोई त्रुटि नहीं है, लेकिन रनटाइम पर, मुझे निम्नलिखित डिबग लॉग मिले हैं जिन्हें मैंने कंस्ट्रक्टर में रखा है:

tmdb-api.ts:30 TMDbApiProvider:constructor-->logger is NULL !!!

tmdb-api.ts:34 TMDbApiProvider:constructor-->http is NULL !!!

और निम्न त्रुटि:

ERROR Error: Uncaught (in promise): TypeError: _this.settingsStorage.loadSettings is not a function
TypeError: _this.settingsStorage.loadSettings is not a function
    at tmdb-api.ts:48
    at new t (polyfills.js:3)
    at TMDbApiProvider.webpackJsonp.171.TMDbApiProvider.searchMovies

अगर मैं कंस्ट्रक्टर में इंजेक्ट की गई सेवाओं के क्रम को उलट देता हूं:

@Injectable()
export class TMDbApiProvider {

    constructor(public http: Http, public logger: Logger,
    public settingsStorage: SettingsStorageProvider) {

मुझे कंस्ट्रक्टर में अलग-अलग डिबग लॉग मिले हैं:

TMDbApiProvider: कंस्ट्रक्टर -> सेटिंग्स स्टोरेज न्यूल है !!! tmdb-api.ts:31 TMDbApiProvider:constructor-->logger is NULL !!!

और त्रुटि भी बदल गई है:

ERROR Error: Uncaught (in promise): TypeError: Cannot read property 'loadSettings' of undefined
TypeError: Cannot read property 'loadSettings' of undefined

ऐसा लगता है कि केवल पहली सेवा जिसे TMDbApiProvider कंस्ट्रक्टर में बुलाया गया है, को इंजेक्ट किया गया है।

क्या कभी किसी ने इस अजीब व्यवहार का सामना किया है? आप मुझे जो भी मदद दे सकते हैं उसके लिए अग्रिम धन्यवाद।

[15/08/2017] यहाँ मेरी समस्या के लिए एक पूरक जानकारी है:

"घोषणाओं", "आयात", "एंट्रीकंपोनेंट्स" और myApp के "प्रदाताओं" के साथ रूट "NgModule": NgModuleऔर "Augury" क्रोम एक्सटेंशन का उपयोग करके myApp के इंजेक्टर ग्राफ का एक दृश्य: इंजेक्टर ग्राफ़

अजीब तरह से, "TMDbAPIProvider" को रूट "NgModule" में एक प्रदाता के रूप में घोषित किया गया है जो इंजेक्टर ग्राफ का हिस्सा नहीं है ... क्या किसी को पता है कि ऐसा क्यों हो सकता है? आपकी मदद के लिए अग्रिम धन्यवाद (यह मुझे पागल कर रहा है!)

enter image description here

2
Eng 14 अगस्त 2017, 20:04
मेरा अनुमान है कि आप DI का उपयोग करने के बजाय कहीं new TMDbApiProvider(someValueOfAnyType) को कॉल कर रहे हैं।
 – 
JB Nizet
14 अगस्त 2017, 20:35
@JBNizet अनुमान लगाने के लिए धन्यवाद। लेकिन मैं 'MoviesHomePage' घटक में TMDbApiProvider के लिए DI का उपयोग करता हूं: export class MoviesHomePage { constructor(public navCtrl: NavController, private logger: Logger, public tmdbApi: TMDbApiProvider) {....
 – 
Eng
15 अगस्त 2017, 01:27
ठीक है, ऐसा लगता है कि "प्राप्त करें" फ़ंक्शन को एक स्थिर फ़ंक्शन के रूप में घोषित करने का कारण था कि मैं इस सेवा को किसी अन्य प्रदाता में इंजेक्ट नहीं कर पाया: static get parameters() { return [[Http]]; } लेकिन मुझे वास्तव में समझ में नहीं आता कि क्यों...
 – 
Eng
27 अगस्त 2017, 10:08

1 उत्तर

सबसे बढ़िया उत्तर

हां, यदि आपको DI के माध्यम से उस सेवा का उपयोग करने की आवश्यकता है, तो आपको parameters() विधि पर static कीवर्ड को निकालना होगा। वह डिज़ाइन द्वारा है। लेकिन यदि आपको आवश्यकता है Static विधियों का उपयोग करें, तो आपको उस वर्ग को DI के माध्यम से तत्काल करने की आवश्यकता नहीं है। जब आप घटक पर इसकी आवश्यकता होती है तो आप इसे नीचे की तरह उपयोग कर सकते हैं:

import { TMDbApiProvider } from './TMDbApiProvider';

export class YourComponent {

    constructor() {
        // This is just an example of accessing the static members of a class.
        // Note: we didn't inject the service, nor manually instantiate it 
        let value = TMDbApiProvider.parameters();
     }
  }
1
Sampath 27 अगस्त 2017, 12:53