【问题标题】:Loop pause with Q用 Q 循环暂停
【发布时间】:2014-06-09 10:24:11
【问题描述】:

我在 a 中使用 Q 对某些文本行 (demo) 进行一些 jQuery 顺序处理。现在我添加了一个暂停按钮来暂时停止forEach 循环内的处理,但是如果我在while-循环内添加一个promise.delay(300)(参见下面的部分代码),我的浏览器就会挂起。如何使用 Q 在 forEach 循环中对布尔值 isPaused 实现条件暂停?

var promise = new Q();

promise = promise.then(function () {
    lines.forEach(function (item) {

        // Browser starts to hang here if isPaused == true
        promise = promise.then(function () {
            while (isPaused) {
                promise = promise.delay(300);
            }
        });

        // The following does not work either
        // while (isPaused) {
        //  promise = promise.delay(300);
        //}


        // The following does not work either
        // while (isPaused) {
        //  Q.delay(300);
        //}

        if (item[0] == '%') {
            promise = promise.then(function ()
            { return addPrompt(wnd); })
            promise = promise.then(function ()
            { return addInput(item.substr(1)); })
        }
        else {
            promise = promise.then(function ()
            { return addOutput(item, wnd); })
        }
    });
    promise = promise.then(function ()
    { return addPrompt(wnd); })
});
promise.done();

【问题讨论】:

    标签: jquery promise q


    【解决方案1】:

    在这种情况下,Promise 仍然是异步的。 while(true) 中的循环将继续执行,同时不会运行其他代码。

    您根本无法在普通的旧浏览器 JavaScript 中使用 while(condition) { /* block that does not change 'condition' /* }。在您的情况下,更改 isPaused 的代码永远不会有机会执行。 (嗯,你可以使用 ES6 生成器,让你显式地让出控制,但这里是 OT)。

    您需要改为递归链式承诺。

    promise = promise.then(function pollUntil(){
         return Q.delay(300).then(function(){
             // recursively chain the continuation here this will check every 300 ms
             // rather than freeze the code.
             return isPaused ? pollUntil() : true; 
         });
    });
    

    这读作:使用 pollUntil 继续当前操作,延迟 300 毫秒,然后重复(调用自身)直到 isPaused 不再为真。

    注意,您不能将.then 添加到外部承诺中,因为您(或者在更一般的情况下可能需要)稍后链接到它。

    当然,最好创建一个 pause() 承诺,当您不再暂停时将解决。

    【讨论】:

    • 附带说明,您正在按顺序处理所有行。我认为这是故意的 - 如果不是,请告诉我。
    • 我认为它必须是 Q.delay(300) 否则它似乎工作。
    • @IngeHenriksen 对,Q.delay,我习惯了来自 ES6 Prollyfills 和 Bluebird 的 Promise.delay,我个人更喜欢 Q (github.com/petkaantonov/bluebird/issues/…)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-03-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多