Dữ liệu phản hồi HTTP có thể lưu bằng cách sử dụng Rxjs Observer / Observable + Cache
Xem mã dưới đây
* từ chối trách nhiệm: Tôi chưa quen với rxjs, vì vậy hãy nhớ rằng tôi có thể đang lạm dụng phương pháp quan sát / quan sát viên. Giải pháp của tôi hoàn toàn là một tập hợp các giải pháp khác mà tôi tìm thấy, và là hậu quả của việc không tìm được một giải pháp tài liệu đơn giản. Vì vậy, tôi đang cung cấp giải pháp mã hoàn chỉnh của mình (như tôi muốn tìm thấy) với hy vọng rằng nó sẽ giúp được người khác.
* lưu ý, cách tiếp cận này dựa trên GoogleFirebaseObservables. Thật không may, tôi thiếu kinh nghiệm / thời gian thích hợp để sao chép những gì họ đã làm dưới mui xe. Nhưng sau đây là một cách đơn giản để cung cấp quyền truy cập không đồng bộ vào một số dữ liệu có thể lưu vào bộ đệm.
Tình huống : Thành phần 'danh sách sản phẩm' được giao nhiệm vụ hiển thị danh sách các sản phẩm. Trang web này là một ứng dụng web một trang với một số nút menu sẽ 'lọc' các sản phẩm được hiển thị trên trang.
Giải pháp : Thành phần "đăng ký" một phương thức dịch vụ. Phương thức dịch vụ trả về một mảng các đối tượng sản phẩm mà thành phần truy cập thông qua cuộc gọi lại đăng ký. Phương thức dịch vụ kết thúc hoạt động của nó trong một Người quan sát mới được tạo và trả về người quan sát. Bên trong người quan sát này, nó tìm kiếm dữ liệu được lưu trong bộ nhớ cache và chuyển nó trở lại thuê bao (thành phần) và trả về. Mặt khác, nó đưa ra một cuộc gọi http để lấy dữ liệu, đăng ký phản hồi, nơi bạn có thể xử lý dữ liệu đó (ví dụ: ánh xạ dữ liệu vào mô hình của riêng bạn) và sau đó chuyển dữ liệu trở lại cho thuê bao.
Mật mã
sản phẩm-list.component.ts
import { Component, OnInit, Input } from '@angular/core';
import { ProductService } from '../../../services/product.service';
import { Product, ProductResponse } from '../../../models/Product';
@Component({
selector: 'app-product-list',
templateUrl: './product-list.component.html',
styleUrls: ['./product-list.component.scss']
})
export class ProductListComponent implements OnInit {
products: Product[];
constructor(
private productService: ProductService
) { }
ngOnInit() {
console.log('product-list init...');
this.productService.getProducts().subscribe(products => {
console.log('product-list received updated products');
this.products = products;
});
}
}
sản phẩm dịch vụ.ts
import { Injectable } from '@angular/core';
import { Http, Headers } from '@angular/http';
import { Observable, Observer } from 'rxjs';
import 'rxjs/add/operator/map';
import { Product, ProductResponse } from '../models/Product';
@Injectable()
export class ProductService {
products: Product[];
constructor(
private http:Http
) {
console.log('product service init. calling http to get products...');
}
getProducts():Observable<Product[]>{
//wrap getProducts around an Observable to make it async.
let productsObservable$ = Observable.create((observer: Observer<Product[]>) => {
//return products if it was previously fetched
if(this.products){
console.log('## returning existing products');
observer.next(this.products);
return observer.complete();
}
//Fetch products from REST API
console.log('** products do not yet exist; fetching from rest api...');
let headers = new Headers();
this.http.get('http://localhost:3000/products/', {headers: headers})
.map(res => res.json()).subscribe((response:ProductResponse) => {
console.log('productResponse: ', response);
let productlist = Product.fromJsonList(response.products); //convert service observable to product[]
this.products = productlist;
observer.next(productlist);
});
});
return productsObservable$;
}
}
sản phẩm.ts (mô hình)
export interface ProductResponse {
success: boolean;
msg: string;
products: Product[];
}
export class Product {
product_id: number;
sku: string;
product_title: string;
..etc...
constructor(product_id: number,
sku: string,
product_title: string,
...etc...
){
//typescript will not autoassign the formal parameters to related properties for exported classes.
this.product_id = product_id;
this.sku = sku;
this.product_title = product_title;
...etc...
}
//Class method to convert products within http response to pure array of Product objects.
//Caller: product.service:getProducts()
static fromJsonList(products:any): Product[] {
let mappedArray = products.map(Product.fromJson);
return mappedArray;
}
//add more parameters depending on your database entries and constructor
static fromJson({
product_id,
sku,
product_title,
...etc...
}): Product {
return new Product(
product_id,
sku,
product_title,
...etc...
);
}
}
Đây là một mẫu đầu ra mà tôi thấy khi tôi tải trang trong Chrome. Lưu ý rằng trên tải ban đầu, các sản phẩm được tìm nạp từ http (gọi đến dịch vụ nghỉ ngơi nút của tôi, đang chạy cục bộ trên cổng 3000). Sau đó, khi tôi nhấp để điều hướng đến chế độ xem 'được lọc' của các sản phẩm, các sản phẩm được tìm thấy trong bộ đệm.
Nhật ký Chrome của tôi (bảng điều khiển):
core.es5.js:2925 Angular is running in the development mode. Call enableProdMode() to enable the production mode.
app.component.ts:19 app.component url: /products
product.service.ts:15 product service init. calling http to get products...
product-list.component.ts:18 product-list init...
product.service.ts:29 ** products do not yet exist; fetching from rest api...
product.service.ts:33 productResponse: {success: true, msg: "Products found", products: Array(23)}
product-list.component.ts:20 product-list received updated products
... [nhấp vào nút menu để lọc sản phẩm] ...
app.component.ts:19 app.component url: /products/chocolatechip
product-list.component.ts:18 product-list init...
product.service.ts:24 ## returning existing products
product-list.component.ts:20 product-list received updated products
Kết luận: Đây là cách đơn giản nhất mà tôi đã tìm thấy (cho đến nay) để triển khai dữ liệu phản hồi http có thể lưu trong bộ nhớ cache. Trong ứng dụng góc cạnh của tôi, mỗi lần tôi điều hướng đến một chế độ xem khác nhau của các sản phẩm, thành phần danh sách sản phẩm sẽ tải lại. ProductService dường như là một trường hợp được chia sẻ, do đó, bộ đệm cục bộ của 'sản phẩm: Sản phẩm []' trong ProductService được giữ lại trong khi điều hướng và các cuộc gọi tiếp theo đến "Get Products ()" trả về giá trị được lưu trong bộ nhớ cache. Một lưu ý cuối cùng, tôi đã đọc các bình luận về cách đóng cửa quan sát / đăng ký khi bạn kết thúc để ngăn chặn 'rò rỉ bộ nhớ'. Tôi đã không bao gồm điều này ở đây, nhưng đó là điều cần lưu ý.