我有一个组件可以从订阅商店获取数据。
this.store.select('somedata').subscribe((state: any) => {
this.somedata = state.data;
});
我想在组件不存在的情况下取消订阅此订阅,在我订阅某些可观察对象的其他地方,如下所示:
this.service.data.subscribe(
(result: any) => {//data}
);
我在ngOnOnDestroy上取消订阅,就像这样:
ngOnDestroy(){
this.service.data.unsubscribe();
}
但是如果商店我无法做到,那就会给我错误:
Property 'unsubscribe' does not exist on type 'Store<State>'
答案 0 :(得分:16)
订阅时,您将收到订阅对象,您可以调用unsubscribe()
const subscription = this.store.select('somedata').subscribe((state: any) => {
this.somedata = state.data;
});
// later
subscription.unsubscribe();
或
ngOnInit(){
this.someDataSubscription = this.store.select('somedata').subscribe((state: any) => {
this.somedata = state.data;
});
}
ngOnDestroy(){
this.someDataSubscription.unsubscribe();
}
答案 1 :(得分:11)
有一个比最高投票答案更好的方法,您不必管理一堆订阅,而只需一个订阅。然后,您可以根据需要拥有任意数量的订阅,而不必创建大量不必要的var。
public ngDestroyed$ = new Subject();
public ngOnDestroy() {
this.ngDestroyed$.next();
}
public ngOnInit() {
this.myWhateverObs$
.pipe(takeUntil(this.ngDestroyed$))
.subscribe((val)=> { this.whatever()});
this.myWhateverNPlusOne$
.pipe(takeUntil(this.ngDestroyed$))
.subscribe((val)=> { this.whatever()})
}
答案 2 :(得分:5)
您可以在不直接调用subscribe方法的情况下获取值,通过异步管道获取值,如
@Component({
template: `
<div>Current Count: {{ counter | async }}</div>
`
})
class MyAppComponent {
counter: Observable<number>;
constructor(private store: Store<AppState>){
this.counter = store.select('counter');
}
}
这里我们使用异步管道来获取价值。 异步管道订阅Observable或Promise并返回它发出的最新值。发出新值时,异步管道会标记要检查更改的组件。当组件被销毁时,异步管道会自动取消订阅以避免潜在的内存泄漏。
答案 3 :(得分:3)
我使用过的最简洁的方法是使用ngx-take-until-destroy库。 您的代码将如下所示:
this.store.select('somedata')
.pipe(untilDestroyed(this))
.subscribe((state: any) => {
this.somedata = state.data;
});
您还需要在类中使用ngOnDestroy()
方法。
答案 4 :(得分:1)
此答案基于by FlavorScape和by mahyar提供的答案。
避免使用主题及其代码使每个组件component肿的一种方法是使用基本组件(已通过Angular 10.0.6测试):
function check_order_product_id( $order_id ){
$order = wc_get_order( $order_id );
$items = $order->get_items();
$order_email = $order->billing_email;
//create custom mail
function get_custom_email_html( $order, $heading = false, $mailer ) {
$template = 'emails/my-custom-email-i-want-to-send.php';
return wc_get_template_html( $template, array(
'order' => $order,
'email_heading' => $heading,
'sent_to_admin' => false,
'plain_text' => false,
'email' => $mailer
) );
}
function send_custom_email($order_email, $order){
// load the mailer class
$mailer = WC()->mailer();
//format the email
$recipient = $order_email;
$subject = __("Deine Login-Daten für Geomap", 'theme_name');
$content = get_custom_email_html( $order, $subject, $mailer );
$headers = "Content-Type: text/html\r\n";
//send the email through wordpress
$mailer->send( $recipient, $subject, $content, $headers );
}
function email_exists( $order_email ) {
$user = get_user_by( 'email', $order_email );
if ( $user ) {
send_custom_email($order_email, $order);
//not sure where this variable was comming from
return $wp_new_user_notification_email;
}
else {
// random password with 12 chars
$random_password = wp_generate_password();
// create new user with email as username & newly created pw
$user_id = wp_create_user( $order_email, $random_password, $order_email );
//not sure where this variable was comming from
return $wp_new_user_notification_email;
}
}
foreach ( $items as $item_id => $item ) {
$product_id = $item->get_variation_id() ? $item->get_variation_id() : $item->get_product_id();
if ( $product_id === XYZ ) {
//get the user email from the order and check if registered already
email_exists( $order_email );
}
}
}
import { Subject } from "rxjs";
import { Component } from "@angular/core";
@Component({
selector: "app-base-component",
template: ""
})
export class BaseComponent {
public ngDestroyed$ = new Subject();
public onDestroy(): void {
this.ngDestroyed$.next();
}
}
您可以使用@ngneat/until-destroy库来避免自定义代码,并支持其他方案(例如在服务内)
@Component({
selector: "app-foo",
templateUrl: "./foo.component.html",
styleUrls: ["./foo.component.scss"]
})
export class FooComponent extends BaseComponent implements OnInit, OnDestroy {
fooList$: Observable<FooModel[]>;
@ViewChild(DataBindingDirective) dataBinding: DataBindingDirective;
public gridData: any[];
public gridView: any[];
public mySelection: string[] = [];
constructor(private readonly store: Store<AppState>) {
super();
}
ngOnDestroy(): void {
this.onDestroy();
}
ngOnInit(): void {
this.store.dispatch(ApplicationFooItemsRequestedAction());
this.fooList$ = this.store.select(selectAllApplicationFooItems);
this.fooList$.pipe(takeUntil(this.ngDestroyed$)).subscribe(ul => {
// do stuff with items
});
}
}