观察ES6模块属性

use*_*960 5 javascript observer-pattern ecmascript-6 object.observe

我有一个模块:

var progress = {
    val: 0
};

var service = (function(){

    function someMethod(){
        progress.val++;
    }

    return{
        someMethod: someMethod
    };

})();

export {service,progress}
Run Code Online (Sandbox Code Playgroud)

someMethod将执行迭代数组的操作.我想progress.val在每次迭代时增加1.然后应该观察到这一进展:

  System.import('components/Service.js')
   .then(function(M){
            self.progress = M.progress;

           Object.observe(M.progress,function(c){
               console.dir(c);
           });
       });
Run Code Online (Sandbox Code Playgroud)

不幸的是,观察者回调只被调用一次,每次迭代持有一个项目的变化数组.

如何在每次迭代时调用回调?

小智 4

这就是对象观察的工作原理。

观察者只会在时钟的下一个滴答声时触发收集记录。它不会在进行个别更改时同步触发。另请参阅Object.Observe 同步回调

为了实现你想要的,一种方法是重写你的迭代器,以便它每次循环时都“休眠”,以便有Object.observe机会触发。我不一定推荐这种精确的方法,只是举个例子:

function iterate(a, fn) {
    (function loop() {
        if (!a.length) return;
        fn(a.shift());
        setTimeout(loop); 
    })();
}
Run Code Online (Sandbox Code Playgroud)

现在,对观察对象的属性所做的任何更改都fn将在循环迭代期间报告。

你可以使用 Promise 完成同样的事情:

function iterate(a, fn) {
    a.reduce((p, e) => p.then(() => fn(e)), Promise.resolve());
}
Run Code Online (Sandbox Code Playgroud)

如果您碰巧处于 async/await 环境中(这是 ES7 功能,但在 Babel 等转译器中可用),那么您还可以执行以下操作,这在幕后大约相当于上面的 Promise 方法:

async function iterate(a, fn) {
    for (i of a) await fn(i);
}
Run Code Online (Sandbox Code Playgroud)

顺便说一句,你在这里不需要 IIFE。另外,self没有声明——我预计会出现运行时错误self.progress = M.progress

  • wait 不是 ES7 的一个特性吗? (2认同)
  • 当然,我只是认为应该指出这一点,因为这个问题是专门关于 ES6 的 (2认同)