Использовать фильтр или конвейер для загрузки категорий продуктов на страницы в Ionic 2?

Я хочу создать приложение Ionic 2 с 6 страницами, я не уверен, использовать ли канал или фильтр для отдельных страниц категорий и код, который мне нужен для этого.

Каждая страница категории может загружать соответствующие продукты, определенные категорией «applecat». Ниже представлен API, отображение продуктов в формате электронной таблицы через Google Таблицы и очень быстрый макет домашней страницы:

https://sheetsu.com/apis/v1.0/04c2d2906a10 https://docs.google.com/spreadsheets/d/1RNLXsxTFymqRwq_S538qX1p1PAEDIEA6s5sV8etkfLU/edit?usp=sharing

введите описание изображения здесь

ОБЗОР

6 страниц

  • домой - товары не нужно загружать - только ссылки на страницы
  • allproducts - загружает ВСЕ продукты
  • ipad - загружает все элементы, перечисленные как ipad в категории applecat
  • iphone - загружает все элементы, перечисленные как iphone в категории applecat
  • клавиатура - загружает все элементы, перечисленные как iphone в категории applecat
  • ноутбук - загружает все элементы, перечисленные как iphone в категории applecat

СЦЕНАРИЙ (потенциальный поток пользователей)

Пользователь открывает приложение, нажимает «Домой», затем ссылку категории «Ipad» (загружает все продукты Ipad), затем возвращается на «Домой», решает нажать «Все» (загружает ВСЕ продукты), назад и щелкает на другой странице ....

ПРОБЛЕМА

Будет ли загружено 2 массива в память / консоль? Должны ли страницы категорий использовать фильтр или канал? Как код должен искать канал / фильтр по отношению к моему существующему вызову API и массиву списка продуктов?

ПРОВАЙДЕРЫ

getRemoteData(): any{
        return this.http.get('https://sheetsu.com/apis/v1.0/04c2d2906a10')
                .map(res => res.json());
}

СПИСОК СТРАНИЦЫ

@Component({
selector: 'page-master',
templateUrl: 'master.html',
providers: [Sheetsu]
})
export class MasterPage {

// declare publicly accessible variable
public sheetsuData: any;

constructor(public navCtrl: NavController, public navParams: NavParams, public sheetsuService: Sheetsu) {}

ionViewDidLoad() {
    this.sheetsuService.getRemoteData()
    .subscribe(response => {
    // assign variable (async)
    this.sheetsuData = response;
    });
}

Я видел пример фильтра со сбросом, но не уверен, применимо ли это в этой ситуации?

 resetData(){
    this.modifiedData = JSON.parse(JSON.stringify(this.originalData));
  }

  filterData(){
    this.modifiedData = this.modifiedData.filter((youtuber) => {
        return youtuber.subscribers > 1000000;
    }
  }

Возможно, при таком небольшом количестве страниц категорий лучшим вариантом для каждой страницы будет труба? Просто потенциальная проблема множественных вызовов API, если пользователи просматривают все 6 страниц.

Предпочтительный ответ на вознаграждение: код для канала / фильтра / службы, советы по лучшему решению и почему, еще лучше - базовый рабочий пример в Github (вызов API для поставщика и список кода ts указаны выше).

Репозиторий Github для этого можно просмотреть и разветвить на странице https://github.com/jones98/4cat.

Видео приложения в текущем состоянии (страницы с предварительными категориями работают) можно просмотреть по адресу https://drive.google.com/file/d/0B0QBawqyq1vPZ0o4WEpaa0o0azQ/view


person me9867    schedule 09.02.2017    source источник


Ответы (2)


Вы можете создать службу, которая кэширует данные (возможно, на 5 минут, 30 минут, один час или любой временной интервал, который имеет смысл в контексте вашего приложения), чтобы избежать выполнения такого большого количества HTTP-запросов, а также будет возвращать только что вам нужно, чтобы вы могли использовать его непосредственно в компоненте / представлении, ничего не фильтруя.

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

Предположим, у вас уже есть класс для продуктов:

export class ProductModel {
    public aw_deep_link: string;
    public product_name: string;
    public apple_cat: string;
    //...
}

Затем мы можем создать нашу модель кеша следующим образом:

class ProductCache {
    public products: Array<ProductModel>;
    public timestamp: number;

    public isValid(): boolean {
        if(!this.products) {
            return false;
        }

        let isExpired = Date.now() - this.timestamp > 1800000; // 30 min
        return !isExpired;
    }
}

а затем мы можем использовать его в нашей ProductCategoryService

// Angular imports
import { Injectable } from '@angular/core';
import { Http } from '@angular/http';

// Rxjs imports
import { Observable } from 'rxjs';
import 'rxjs/add/operator/map';

@Injectable()
export class ProductCategoryService {

    private cache: ProductCache;
    private apiUrl: string = 'https://sheetsu.com/apis/v1.0/04c2d2906a10';

    constructor(private http: Http) {
        this.cache = new ProductCache();
    }

    public getAll(): Observable<Array<ProductModel>> {
        if(this.cache.isValid()) {
            // Return the products from the cache
            return Observable.of(this.cache.products);
        }

        // Cache is empty/expired, so we need to make the http request
        return this.http.get(this.apiUrl).map(res => res.json()).map(data => {
            // Save the data in the cache for the next time
            this.cache.products = data;
            this.cache.timestamp = Date.now();

            // Return the list of (all) products
            return this.cache.products;
        });
    }

    public getIpadProducts(): Observable<Array<ProductModel>> {
        return this.getAll().filter((product: ProductModel) => {
            return product.apple_cat.toLowerCase() === 'ipad';
        });
    }

    public getIphoneProducts(): Observable<Array<ProductModel>> {
        return this.getAll().filter((product: ProductModel) => {
            return product.apple_cat.toLowerCase() === 'iphone';
        });
    }

    // ...
}

А затем просто вызовите правильный метод на каждой странице, и HTTP-запрос будет выполняться только один раз (или каждые 30 минут в этом примере) из-за кеша продукта.

Могут быть синтаксические ошибки или опечатки (я закодировал непосредственно в ответе SO), но это должно дать вам представление о том, как действовать в данном сценарии. Пожалуйста, дайте мне знать, если что-то не работает должным образом, я могу помочь вам это исправить ...

ОБНОВЛЕНИЕ: здесь вы можете найти некоторую информацию (из Angular 2 Docs) о том, почему использование каналов для фильтрации данных не очень хороший подход, и поэтому я рекомендую делать это в сервисе, сохраняя его скрытым для остальной части приложения (в конце концов, каждая страница категории просто хочет получить данные, которые она должна отображать, ей не нужно иметь дело со всеми продуктами, чтобы затем найти только те, которые она должна отображать в представлении ).

person sebaferreras    schedule 11.02.2017
comment
Итак, создали новую службу с ionic g provider ProductCategory. В github.com/jones98/4cat добавлено рабочее приложение с видео. Было бы здорово, если бы эта часть ProductCategory работала на страницах категорий. Не знаю, какие детали мне нужны в данный момент. - person me9867; 12.02.2017
comment
Я создал этот запрос на вытягивание с необходимыми изменениями для добавления логики кеширования. Пожалуйста, взгляните, я думаю, что код очень простой. - person sebaferreras; 12.02.2017
comment
Огромное спасибо за ваши усилия здесь. Я полностью ударился этим о кирпичную стену, работает как мечта! Блестящий вклад. Огромное спасибо - person me9867; 14.02.2017
comment
Это отлично работает, но если нет интернета. Спиннер просто крутится, и вам нужно принудительно закрыть приложение. Есть ли способ добавить тайм-аут спиннерам? github.com/jones98/4cat/blob/master/ src / pages / laptop / laptop.ts и github.com/jones98/4cat/blob/master/src/providers/ - person me9867; 23.04.2017

Мне также следует создать службу под названием ProductCategoryService.

ionic g provider ProductCategory

И создайте метод, который я мог бы выполнить с именем категории в качестве параметра

getProductsByCategoryName(categoryName): any{
  return this.allProducts.filter(product => product.categoryName === categoryName);
}

Взамен я бы получил отфильтрованный массив с моими продуктами, привязал его к вашему шаблону, и все готово.

person 0x1ad2    schedule 17.02.2017