2016-09-29 74 views
1

我一直在玩承诺,并试图建立某种进度通知。jQuery推迟承诺进度通知

代码以正确的顺序执行所有函数,但进度更新在解析之前执行,而不是在实际发生时执行。

任何人都可以指出我做错了什么?

function start(x) { 
    console.log("Start: " + x); 
    var promise = process(x); 
    console.log("promise returned"); 
    promise.then(function(data) { 
     console.log("Completed: " + data); 
    }, function(data) { 
     console.log("Cancelled: " + data); 
    }, function(data) { 
     console.log("In Progress: " + data); 
    }); 
    } 

    function process(x) { 
    var deferred = $.Deferred(); 
    var promise = deferred.promise(); 

    // process asynchronously 
    setTimeout(function() { 
     for (var i=0 ; i<x ; i++) { 
     sleep(1000); 
     deferred.notify(i); 
     } 

     if (x % 2 === 0) { 
     deferred.reject(x); 
     } else { 
     deferred.resolve(x); 
     } 
    }, 0); 

    return promise; 
    } 

    function sleep(sleepDuration) { 
    var now = new Date().getTime(); 
    while(new Date().getTime() < now + sleepDuration){ /* do nothing */ } 
    } 

    start(3); 

小提琴这里: https://jsfiddle.net/n86mr9tL/

回答

1

while()实现的延迟计时器,将 “块” - 即猪处理器。

阻止不仅阻止其他javascript运行,而且还阻止包括控制台在内的浏览器屏幕的可靠刷新。所以,那些deferred.notify(i)console.log("In Progress: " + data)语句触发,控制台不会刷新,直到处理器变得空闲。

不出所料,解决方案在于不使用while()

幸运的是,JavaScript的imcludes两个内置的方法window.setTimeout()window.setInterval(),这是从while()惰概念不同,但发挥同样的作用.... 无阻塞

  • window.setInterval(fn, t)火灾作用fn每隔t毫秒,
  • window.setTimeout(fn, t)火灾作用fn一次,T毫秒后。

这两种方法都返回一个不透明的引用,它允许它们被取消。

在下面的代码中,start()未修改,process()进行了大量修改,sleep()已消失。

process()现在将执行以下操作:

  • 创建一个jQuery延迟,并返回从它衍生的承诺,
  • establises 1000的setInterval()一毫秒(1秒),其功能:
    • 保持被调用的次数为
    • 每秒调用deferred.notify()直到计数器i达到规定的最大x
  • 当达到指定的最大值:
    • 的时间间隔,否则会默默流逝循环往复清零时,
    • deferred.resolve()deferred.reject()被称为定居延期(及其承诺),
function start(x) { 
    console.log("Start: " + x); 
    process(x).then(function(data) { 
     console.log("Completed: " + data); 
    }, function(data) { 
     console.log("Cancelled: " + data); 
    }, function(data) { 
     console.log("In Progress: " + data); 
    }); 
} 

function process(x) { 
    return $.Deferred(function(dfd) { 
     var i = 1; 
     var intervalRef = setInterval(function() { 
      if(i < x) { 
       dfd.notify(i++); 
      } else { 
       clearInterval(intervalRef); 
       dfd[(x % 2 === 0)?'reject':'resolve'](x); 
      } 
     }, 1000); 
    }).promise(); 
} 

console.clear(); 
start(3); 

Updated fiddle

+0

尼斯之一。现在都清楚了。 –