Имитация встроенной поддержки Ionic в браузере

Пытаюсь издеваться над Ionic Native Network в браузере. Для этого я добавил class в свой app.module.ts следующим образом:

    ...
    import { Network } from '@ionic-native/network';
    ...
    ...    
    export class NetworkMock extends Network{      
      type = 'none';
    }
@NgModule({ ....


providers: [ 
...
...

{ provide: ErrorHandler, useClass: IonicErrorHandler },
{provide: Network, useClass: NetworkMock}

С учетом вышесказанного, когда я вызываю в компоненте следующую функцию:

check_network() {    
    console.log(this.net.type);    
}

Я получаю null в консоли браузера

Как мне заставить его работать правильно? Разве я не должен получать 'none'?

Ниже приводится вывод ionic-info:

global packages:

    @ionic/cli-utils : 1.4.0
    Cordova CLI      : 6.5.0
    Ionic CLI        : 3.4.0

local packages:

    @ionic/app-scripts              : 1.3.0
    @ionic/cli-plugin-cordova       : 1.4.0
    @ionic/cli-plugin-ionic-angular : 1.3.1
    Cordova Platforms               : none
    Ionic Framework                 : ionic-angular 3.0.1

System:

    Node       : v6.9.1
    OS         : Windows 7
    Xcode      : not installed
    ios-deploy : not installed
    ios-sim    : not installed
    npm        : 3.10.8

Что не так? Пожалуйста помоги.


person Arup Bhattacharya    schedule 28.06.2017    source источник
comment
пожалуйста, взгляните на мой ответ в этом вопросе . Если вы думаете, что это может сработать с вашей стороны, я также могу добавить его в качестве ответа в эту ветку.   -  person sebaferreras    schedule 28.06.2017
comment
подписались ли вы на ionicframework.com/docs/native/network?   -  person Sohan    schedule 28.06.2017
comment
@sebaferreras Я просто перефразировал код и не расширял «NetworkMock», чтобы унаследовать реальный класс «Network» - код работал !! он правильно возвратил "none" на моей консоли браузера. Это из-за странной природы наследования Javascript ???   -  person Arup Bhattacharya    schedule 28.06.2017


Ответы (2)


Я предпочитаю делать что-то немного по-другому, когда дело доходит до использования плагина Cordova в браузере. Несмотря на то, что ваш подход отлично работает, вам все равно нужно вручную указать Angular, какой класс следует использовать, когда он видит параметр Network в конструкторе какого-либо компонента. Вы делаете это в этой строке:

{ provide: Network, useClass: NetworkMock } 

Итак, если вы хотите запустить приложение на мобильном устройстве, вам нужно будет вручную изменить эту строку (а также все строки, относящиеся к некоторым другим плагинам Cordova).

Вот почему мне нравится использовать заводской поставщик вместо. Вот как я работаю с плагином Network cordova в браузере:

// ------------------------------------------------------------
// File: /providers/cordova-plugins/network/network.provider.ts
// ------------------------------------------------------------

// Ionic
import { Platform } from 'ionic-angular';

// Ionic native
// http://ionicframework.com/docs/v2/native/network/
import { Network } from '@ionic-native/network';

// Browser implementation
export class BrowserNetworkProvider extends Network {

    public get type(): string {
        return this.isOnline() ? 'wify' : 'none';
    }

    private isOnline(): boolean {
        return navigator.onLine;
    }
}

// Mobile implementation
// Is empty in this case since I don't to override anything, but in 
// some other plugins, I like to add some console.log() before calling
// the methods in the plugin (by using super.nameOfTheMethod();)
export class MobileNetworkProvider extends Network {}

// ------------------------------------------------------------
// Network factory
//    parameters: dependencies of the target service
//    returns: instance of the service (for real devices or the browser)
// ------------------------------------------------------------
export function networkFactory(platform: Platform) {
    return platform.is('cordova') ? new MobileNetworkProvider() : new BrowserNetworkProvider();
}

// networkProvider: used to import the service in the NgModule declaration
export let networkProvider =
    {
        provide: Network,
        useFactory: networkFactory,
        deps: [Platform]
    };

А затем в файле app.module.ts:

import { networkProvider } from '../providers/plugins/network/network.provider';

@NgModule({
    declarations: [
        MyApp,
        //...
    ],
    imports: [
        // ...
    ],
    bootstrap: [IonicApp],
    entryComponents: [
        // ...
    ],
    providers: [
        // Cordova plugins
        networkProvider, // <- I'm using our custom provider here! :)

        // ...
    ]
})
export class AppModule { }

Как видите, Angular будет использовать информацию Platform, чтобы узнать, какое расширение класса Network следует использовать в нашем приложении.


Как мы уже говорили в комментариях:

1) Что касается геттера для переопределения свойства type, я не знаю так много в Typescript, но по какой-то причине мне не удалось установить значение свойства при расширении класса (поэтому я предложил вместо этого использовать геттер) . Поскольку геттер вызывается так же, как если бы он был свойством, я подумал о том, чтобы сделать это так, и, похоже, он работает!

2) Зачем расширять класс Network для браузера, если мы могли бы также использовать класс, не имеющий ничего общего с классом Network (например, когда вы опускаете ключевое слово extend в своем примере? Что ж, вы могли бы это сделать, поскольку после всего этого - это просто Javascript (и вы можете исправить любую жалобу на Typescript, используя приведение (<any>propertyName). Но поскольку вы говорите Angular, какую реализацию класса Network следует использовать, почему бы не расширить этот класс, переопределив то, что мы хотим изменить, но сохраняя все согласованным ? Если позже плагин добавит несколько методов, которые работают в браузере, вам не нужно будет ничего менять, поскольку вы уже используете реальную реализацию плагина для всех методов, которые вы не отменяете.

person sebaferreras    schedule 29.06.2017
comment
Я согласен. Это лучшее решение, которое я нашел в Интернете. И я много искал. - person Mario Shtika; 09.02.2018
comment
Рад слышать, что @MarioShtika :) - person sebaferreras; 09.02.2018

Я просто попробовал следующую альтернативу, и она сработала.

...
import { Network } from '@ionic-native/network';
...
...    
export class NetworkMock{   
 // I omitted the Extend keyword and avoided overriding the actual class   
 type = 'none';
}
@NgModule({ ....


providers: [ 
...
...

{ provide: ErrorHandler, useClass: IonicErrorHandler },
{provide: Network, useClass: NetworkMock}

С помощью приведенного выше кода теперь консоль браузера правильно печатает 'none' или любое другое значение, которое я ввел в свойство type класса NetworkMock.

Насколько я понимаю, Inheritance is Javascript сложен по своей природе и приводит к нежелательным обстоятельствам. Так что я полностью избегал этого. Однако в массиве providers я указал свой NetworkMock в свойстве useClass.

Мы будем очень признательны за любую дополнительную информацию.

person Arup Bhattacharya    schedule 28.06.2017
comment
Я думаю, что это сработало, потому что это что-то другое. Расширяя класс Network своим макетом, вы добавляете новые функции. Опуская extend, вы просто создаете новый класс, который не имеет ничего общего с классом Network из Ionic Native. При этом не могли бы вы попробовать, добавив расширение, но используя геттер вместо свойства? Я бы такой: export class NetworkMock extends Network { public get type() { return 'none'; } }. Я почти уверен, что теперь это сработает, но просто проверьте это, если можете, чтобы быть уверенным ... - person sebaferreras; 28.06.2017
comment
@sebaferreras большое спасибо за ваш вклад. Я протестирую как можно скорее и обязательно сообщу вам об обновлении. Еще раз спасибо за вашу помощь. - person Arup Bhattacharya; 28.06.2017
comment
Привет @sebaferreras, я только что проверил ваше предложение, и это сработало. Спасибо за вашу помощь. Но по академическим причинам - позвольте мне спросить - если я создаю функцию получения вместо свойства - я фактически изменяю класс NetworkMock, даже если это дочерний класс Network, и я не переопределяю исходное свойство типа, определенное на суперкласс. В результате, когда вызывается метод, он ищет функцию получения, а не свойство. Вопрос в том ... в чем разница между моим подходом, как указано выше, и тем, что вы предложили? - person Arup Bhattacharya; 29.06.2017
comment
Я добавил ответ с некоторыми деталями и причинами, по которым я предпочитаю другой подход ... но опять же, иногда это просто дело вкуса, и есть много возможных способов сделать это, и все они допустимые варианты :) - person sebaferreras; 29.06.2017