Promise和setTimeout

时间:2017-03-13 19:24:20

标签: javascript promise

我正在尝试确定一种方法来“暂停”我的Promises代码,直到条件为真,可能是通过使用递归setTimeout()。对于我的简单示例,我手动设置waitValue

我需要等待片刻,如果waitValue仍然是假的,那么只需继续等待。当然,当waitValue变为真时,继续处理。以下是我到目前为止拼凑的内容:

var counter=0;
function promiseTest() { 
    return new Promise(  (resolve, reject) => {
        if  ( waitValue )  {
            console.log('waitValue is now true');
            resolve('FIRST PROMISE');
        } else  {                      // we need to wait again
            if  ( counter > 1000 ) {   // dont wait forever.
                reject('waited too long');
            } else {
                console.log('WAIT MESSAGE: ' + counter++ );
                setTimeout( promiseTest, 3000);
            }
        }
    })
    .then(   result => {
        return(`SECOND PROMISE:  the result is: ${result}`);
    });
}

使用它:

promiseTest().then( (result)=>{ console.log('LOCAL MESSAGE: ' + result); });

以下工作正常:

var waitValue = true;
promiseTest().then( (result)=>{ console.log('LOCAL MESSAGE: ' + result); });
// waitValue is now true
// LOCAL MESSAGE: SECOND PROMISE:  the result is: FIRST PROMISE

但是,以下似乎并不像我想要的那样完成:

var waitValue = false;
promiseTest().then( (result)=>{ console.log('LOCAL MESSAGE: ' + result); });
// waiting messages appear as expected
waitValue = true;
// waitValue is now true
// no other messages

我一直无法找到暂时执行的承诺示例。普通的javaScript示例可能如下所示:

var waitValue = false;
var counter = 0;
(function tester() {
   if  ( waitValue ) {
      console.log('finally true');
   } else {
       if  ( counter > 1000 ) {
           console.log('waited too long');
           process.exit;
       } else {
           console.log('still waiting, counter = ' + counter++);
           setTimeout(tester, 1000);
       }
   }
})();
// wait a few seconds and enter this into the console:
var waitValue = false;

Promises脚本暂时暂停执行会是什么样的?或者也许不应该像这样使用Promise?

非常感谢。

2 个答案:

答案 0 :(得分:1)

这个想法是朝着正确的方向发展的。当你以递归方式调用函数时,你只需要解决当前的承诺,否则你当前的承诺永远不会实现。

但请注意,如果等待时间很长,则会创建一堆promises。



function promiseTest(counter = 1000) { 
    return new Promise(  (resolve, reject) => {
        if ( waitValue )  {
            console.log('waitValue is now true');
            resolve('FIRST PROMISE');
        } else if  ( counter <= 0 ) {   // dont wait forever.
            reject('waited too long');
        } else {
            console.log('Count down: ' + counter);
            setTimeout( _ => { // make sure to call `resolve` after the nested promise resolved:
                promiseTest(counter-1).then(resolve);
            }, 3000);
        }
    })
    .then(   result => {
        return `SECOND PROMISE:  the result is: ${result}`;
    });
}

var waitValue = false;

promiseTest().then ( result => {
   console.log('done:', result);
});

// schedule the change of the waitValue:
setTimeout(_ => waitValue = true, 4000);
&#13;
&#13;
&#13;

注意输出将如何解决每个已解决的嵌套链式承诺的痕迹。

替代

我发现对你在 Promise构造函数回调中定义的函数执行递归调用更直观,而不是在创建Promise的函数上执行。这样你就可以创建一个承诺,并且避免出现在你的想法中的promise constructor anti-pattern(以及它的上述工作版本):

&#13;
&#13;
function promiseTest(counter = 1000) { 
    return new Promise(  (resolve, reject) => {
        (function loop(counter) {
            if ( waitValue )  {
                console.log('waitValue is now true');
                resolve('FIRST PROMISE');
            } else if  ( counter <= 0 ) {   // dont wait forever.
                reject('waited too long');
            } else {
                console.log('Count down: ' + counter);
                setTimeout( loop.bind(null, counter-1), 3000);
            }
        })(counter); // initial value of count-down
    })
    .then(   result => {
        return `SECOND PROMISE:  the result is: ${result}`;
    });
}

var waitValue = false;

promiseTest().then ( result => {
   console.log('done:', result);
});

// schedule the change of the waitValue:
setTimeout(_ => waitValue = true, 4000);
&#13;
&#13;
&#13;

请注意输出与第一个版本略有不同,这反映出只涉及一个new承诺

注意:它不是必需的,但我更喜欢从某个值(1000)开始倒计时,并将其作为参数传递给执行循环的匿名函数。

答案 1 :(得分:0)

setTimeout( promiseTest, 3000);不起作用,这可能会再次调用promiseTest函数,但永远不会解析在最外层调用中创建的承诺。

而不是乱用回调,promisify你正在使用的异步原语,setTimeout

function wait(t) {
    return new Promise(resolve => {
        setTimeout(resolve, t);
    });
}

然后在轮询功能中使用它:

function promiseTest(counter = 1000) {
    if (waitValue) {
        console.log('waitValue is now true');
        return Promise.resolve('FIRST PROMISE');
    } else if (counter <= 0) { // dont wait forever.
        return Promise.reject(new Error('waited too long'));
    } else {
        console.log('WAIT MESSAGE: ' + counter );
        return wait(3000).then(() => {
            return promiseTest(counter-1);
        });
    }
}