angular - 如何解决 Ionic Angular 应用程序中的“数字”类型错误不存在属性订阅?
问题描述
以下代码在 Ionic 5 / Angular 教程中用于更新Place
对象。我正在尝试将相同的代码应用于我更新Conversation
对象的项目:
地方服务:
private _places = new BehaviorSubject<Place[]>([
new Place(
'p1',
'Manhattan Mansion',
'In the heart of New York City.',
'https://lonelyplanetimages.imgix.net/mastheads/GettyImages-538096543_medium.jpg?sharp=10&vib=20&w=1200',
149.99,
new Date('2019-01-01'),
new Date('2019-12-31'),
'abc'
)
]);
get places() {
return this._places.asObservable();
}
updatePlace(placeId: string, title: string, description: string) {
return this.places.pipe(
take(1),
delay(1000),
tap(places => {
const updatedPlaceIndex = places.findIndex(pl => pl.id === placeId);
const updatedPlaces = [...places];
const oldPlace = updatedPlaces[updatedPlaceIndex];
updatedPlaces[updatedPlaceIndex] = new Place(
oldPlace.id,
title,
description,
oldPlace.imageUrl,
oldPlace.price,
oldPlace.availableFrom,
oldPlace.availableTo,
oldPlace.userId
);
this._places.next(updatedPlaces);
})
);
}
这是Place
模型:
export class Place {
constructor(
public id: string,
public title: string,
public description: string,
public imageUrl: string,
public price: number,
public availableFrom: Date,
public availableTo: Date,
public userId: string
) {}
}
如您所见,上述updatePlace()
方法在调用时可以订阅。
我正在尝试创建一个addMessageToConversation()
也可以订阅的方法,就像上面一样。
到目前为止,这是我的代码:
对话服务:
private _conversations = new BehaviorSubject<Conversation[]>([
new Conversation(
'conversation1',
'user3',
'user1',
[
new Message('message1', 'Test message', 'user3', new Date(2018, 0O5, 0O5, 17, 23, 42, 11)),
new Message('message2', 'Another message', 'user1', new Date(2018, 0O6, 0O5, 17, 23, 42, 11))
])
]);
get conversations() {
return this._conversations.asObservable();
}
addMessageToConversation(conversationId: string, message: string) {
this._conversations.getValue().find(conversation => conversation.id === conversationId)
.messages.push(
new Message(
Math.random().toString(),
message,
this.authService.userId,
new Date(Date.now())
));
}
这里是Conversation
&Message
模型:
export class Conversation {
constructor(
public id: string,
public userId: string,
public mechanicId: string,
public messages: Message[]
) { }
}
export class Message {
constructor(
public id: string,
public text: string,
public userId: string,
public timestamp: Date
) { }
}
上面的代码确实更新conversations
了,但我无法订阅该方法。有人可以告诉我我需要做哪些改变才能做到这一点吗?
如果我return
在其中addMessageToConversation()
并尝试使用subscribe
它,我会收到以下错误消息:
subscribe
类型“数字”上不存在属性
另外,如果我尝试删除_
from this._conversations.getValue().find(conversation => ...
,则会收到以下错误消息:
“可观察”类型上不存在属性“getValue”
解决方案
BehaviorSubject
您可以从开箱即用中获取对话数组,因为它总是将最后一个值重新发送给新订阅者。然后剩下的就很简单了。
import {switchMap} from 'rxjs/operators';
import {empty} from 'rxjs';
// Obs: notice we're returning a void observable (the empty() at the end),
// to avoid returning an out-of-date value for the modified conversation.
addMessageToConversation(
conversationId: string,
message: string
): Observable<Conversation> {
return this._conversations.pipe(
take(1),
map((conversations) => conversations.find(c => c.id === conversationId)),
tap((c: Conversation) => {
// return case c or messages is falsey
if(!c?.messages) {return;}
c.messages.push(
new Message(
Math.random().toString(),
message,
this.authService.userId,
new Date(Date.now())
));
// Re-emit conversations array (with new reference)
this._conversations.next(JSON.parse(JSON.stringify(this._conversations])));
}),
// This step is optional, just to avoid returning an out-of-date conversation
switchMap((_oldConversation: Conversation) => empty())
);
}
你可以像这样使用它:
addMessageToConversation('conversation1', 'Hey, look! A new message')
.subscribe();
推荐阅读
- archunit - ArchUnit 规则来测试@Service 只依赖于自己包中的@Repository?
- angular - 从订阅内的 ngx-translate 获取翻译值
- java - 如何使用 Rest Assured 将多个文件作为输入传递给 api
- jquery - 将参数值从 jquery 数据表 ajax 传递给控制器
- angular - 从类似点击的事件中订阅 observable 的 Angular 首选实践
- flutter - Flutter SVG 作为 ImageIcon
- linux - 如何使用 shell 脚本读取一周、一个月的日志数据?
- for-loop - Rust 正在跳过 for 循环
- jquery - 单击按钮时的 jQuery 函数,然后显示动画并加载新页面
- django - REST 框架检索到错误的数据