Rxjs 观察对象更新和变化
Posted
技术标签:
【中文标题】Rxjs 观察对象更新和变化【英文标题】:Rxjs observing object updates and changes 【发布时间】:2015-12-17 11:03:17 【问题描述】:我目前正在尝试观察给定对象的任何变化,包括它的所有元素。
以下代码仅在更新 object[x] 时触发,但不会在单独更新 object[x] 的元素(例如 object[x][y])时触发
<script>
var elem = document.getElementById("test1");
var log = function(x)
elem.innerhtml += x + "<br/><br/><br/>";
;
var a = [a:1,b:2,
a:2,b:5
];
var source = Rx.Observable
.ofObjectChanges(a)
.map(function(x)
return JSON.stringify(x);
);
var subscription = source.subscribe(
function (x) log(x);,
function (err) log(err);,
function () log('Completed');
);
a[0] = a[1];
</script>
此代码正确运行和触发。
然而。如果我改为这个
a[0]['a'] = 3;
然后什么都没有发生。
编辑
更好的表达方式是,如何观察对象数组的变化?
【问题讨论】:
可能从使用ofArrayChanges
开始。
【参考方案1】:
这是一个 Rx.Observable.ofNestedObjectChanges 简单实现的工作示例,您可以了解它的要点并自己实现。
http://jsbin.com/wekote/edit?js,console
Rx.Observable.ofNestedObjectChanges = function(obj)
if (obj == null) throw new TypeError('object must not be null or undefined.');
if (typeof Object.observe !== 'function' && typeof Object.unobserve !== 'function') throw new TypeError('Object.observe is not supported on your platform')
return new Rx.AnonymousObservable(function(observer)
function observerFn(changes)
for(var i = 0, len = changes.length; i < len; i++)
observer.onNext(changes[i]);
Object.observe(obj, observerFn);
//Recursive observers hooks - same observerFn
traverseObjectTree(obj, observerFn);
function traverseObjectTree(element, observerFn)
for(var i=0;i<Object.keys(element).length;i++)
var myObj = element[Object.keys(element)[i]];
if(typeof myObj === "object")
Object.observe(myObj, observerFn);
traverseObjectTree(myObj,observerFn);
return function ()
Object.unobserve(obj, observerFn);
;
);
;
//Test
var json =
element :
name : "Yocto",
job :
title: "Designer"
,
element1:
name : "Mokto"
;
setTimeout(function()
json.element.job.title = "A Great Designer";
,3000);
var source = Rx.Observable.ofNestedObjectChanges(json);
var subscription = source.subscribe(
function (x)
console.log(x);
,
function (err)
console.log('Error: %s', err);
,
function ()
console.log('Completed');
);
json.element.name = "Candy Joe";
【讨论】:
已在 Safari 和 Chrome 中签出。链接提供的片段似乎已损坏。【参考方案2】:通过合并两个 Observables(一个用于数组,另一个用于观察数组的元素)可能是这样的:
var a = [
a:1,b:2,
a:2,b:5
];
var source1 = Rx.Observable.ofArrayChanges(a).map(function(x)
return JSON.stringify(x);
);
var source2 = Rx.Observable
.fromArray(a.map(function(o, i) return [o, i]; ))
.flatMap(function(oi)
return Rx.Observable.ofObjectChanges(oi[0])
.map(function(x)
var y =
type: x.type,
object: x.object,
name: x.name,
oldValue: x.oldValue,
arrayIndex: oi[1] // pass the index of the member that changed
;
return JSON.stringify(y);
);
)
source = source1.merge(source2)
var subscription = source.subscribe(
function (x) log(x);,
function (err) log(err);,
function () log('Completed');
);
a[0] = a[1]
a[1]['b'] = 7
感谢@electrichead,我们没有使用concatMap
,因为我们由ofObjectChanges
和ofArrayChanges
制作的资源从未完成。
【讨论】:
【参考方案3】:如果您只想更改嵌套对象:
var source = rx.Observable.from(a).flatMap(function(item)
return rx.Observable.ofObjectChanges(item);
);
如果您还想要更改 a[0] = a[1]
:
var source = rx.Observable.merge(
rx.Observable.ofArrayChanges(a),
rx.Observable.from(a).flatMap(function(item)
return rx.Observable.ofObjectChanges(item);
)
);
flatMap
或 selectMany
(它们是同一个函数)将允许您迭代一个值并执行一个返回 Observable 的函数。所有这些 Observable 的值都被“展平”到返回的新流上。
http://reactivex.io/documentation/operators/flatmap.html
【讨论】:
为了使它工作,我需要将 rx 更改为 Rx 并在合并结束时添加 map 函数。酷! 'rx.Observable.ofObjectChanges' 已贬值。 是的,看到这个方法已经贬值了,我很想看看如何在 RxJS 5 中观察对象的变化......以上是关于Rxjs 观察对象更新和变化的主要内容,如果未能解决你的问题,请参考以下文章