Reputation: 1526
I have a module:
var progress = {
val: 0
};
var service = (function(){
function someMethod(){
progress.val++;
}
return{
someMethod: someMethod
};
})();
export {service,progress}
someMethod
will perform an operation where an array is iterated. I would like to increment progress.val
by one at each iteration. This progress should then be observable:
System.import('components/Service.js')
.then(function(M){
self.progress = M.progress;
Object.observe(M.progress,function(c){
console.dir(c);
});
});
Unfortunately, the observers callback is invoked only once, holding an array of changes with one item per iteration.
How can I invoke the callback on each iteration?
Upvotes: 5
Views: 913
Reputation:
That's how object observing works.
The observer will only fire at the next tick of the clock with a collection of records. It does not fire synchronously on individual changes as they are made. See also Object.Observe Synchronous Callback.
To accomplish what you want, one approach is to rewrite your iterator so that it "sleeps" each time through the loop to give Object.observe
a chance to fire. I'm not necessarily recommending this precise approach, but just as an example:
function iterate(a, fn) {
(function loop() {
if (!a.length) return;
fn(a.shift());
setTimeout(loop);
})();
}
Now, any changes to properties made on the observe object by fn
will be reported during that iteration of the loop.
You could accomplish the same thing using promises:
function iterate(a, fn) {
a.reduce((p, e) => p.then(() => fn(e)), Promise.resolve());
}
If you happen to be in an async/await environment (this is an ES7 feature, but available in transpilers such as Babel), then you could also do the following, which under the covers is about equivalent to the promises approach above:
async function iterate(a, fn) {
for (i of a) await fn(i);
}
As an aside, You don't need an IIFE here. Also, self
is not declared--I expect a run-time error on the self.progress = M.progress
line.
Upvotes: 4