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 flatMapor 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 concatMapbecause the sources that we made by ofObjectChangesand ofArrayChangesnever 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";

