Javascript Rxjs 观察对象更新和变化
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/32683488/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Rxjs observing object updates and changes
提问by Andrew Mata
I am currently trying to observe any changes to a given object including all of it's elements.
我目前正在尝试观察给定对象的任何更改,包括它的所有元素。
The following code only fires when an object[x] is updates, but not if individually updating object[x]'s elements such as object[x][y]
以下代码仅在更新 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>
This code runs and fires correctly.
此代码正确运行并触发。
however. if I instead to this
然而。如果我改为这个
a[0]['a'] = 3;
Then nothing happens.
然后什么也没有发生。
EDIT
编辑
A better way to phrase this, how can I observe changes from an array of objects?
更好的表述方式是,如何观察对象数组的变化?
采纳答案by electrichead
If you want only the nested object changes:
如果您只想更改嵌套对象:
var source = rx.Observable.from(a).flatMap(function(item) {
return rx.Observable.ofObjectChanges(item);
});
If you also want changes like a[0] = a[1]
:
如果您还想要更改,例如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);
})
);
The flatMap
or selectMany
(they are the same function) will allow you to iterate over a value and execute a function that returns an Observable. The values from all these Observables are "flattened" onto a new stream that is returned.
该flatMap
或selectMany
(它们是相同的功能)可以让你迭代一个值,并执行函数返回一个观测。来自所有这些 Observable 的值被“展平”到返回的新流上。
回答by homam
Perhaps something like this by merging two Observables (one for the array and the other observing the elements of the array):
也许通过合并两个 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
Thanks to @electrichead here we're not using concatMap
because the sources that we made by ofObjectChanges
and ofArrayChanges
never complete.
由于这里@electrichead我们没有使用concatMap
,因为我们做的来源ofObjectChanges
和ofArrayChanges
永远不会完成。
回答by Gorilla
Here's a working example of Rx.Observable.ofNestedObjectChanges simple implementation, you can get the gist of it and implement you own.
这是 Rx.Observable.ofNestedObjectChanges 简单实现的一个工作示例,您可以了解它的要点并实现您自己的。
http://jsbin.com/wekote/edit?js,console
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";