如何使`.then()`保持足够长的时间来使用本机承诺的轮询函数?

时间:2016-08-05 21:27:00

标签: javascript callback promise

摘要:poll()具有回调函数可用;我没有找到任何使用本机承诺。我试图适应一些没有成功。我还没有解决的问题是,当setTimeout调用的函数的第一个实例结束而没有任何返回时,监听它的.then()会将终止视为false和{{1} }。 reject()终止,不会听取以后的回复。

问题:如何最好地帮助then()功能,以便以后.then()resolve()返回?

这篇文章的其余部分是详细的。阅读有用的内容。

可用的民意调查功能:我喜欢(https://stackoverflow.com/users/1249219/om-shankar)Om Shankar在Calling a function every 60 seconds中的回复。 David Walsh的民意调查()非常相似(https://davidwalsh.name/essential-javascript-functions)。两者都使用回调并且运行良好。我发现 poll in javascript 其中包括使用reject()的{​​{1}} - 仅承诺。

这是我尝试用本机承诺实现的。

poll()

预期用途:

bluebird

我认为这种方式正在运行(如果我错了,请纠正我):在* 1处致电/** * poll - checks repeatedly whether a condition exists. When the condition * exists, returns a resolved standard promise. When it has checked * long enough, returns a rejected standard promise. * @param {function} fn - a caller-supplied synchronous function that * detects a condition in the environment. Returns true if the * condition exists; otherwise false. * @param {number} timeout - maximum number of milliseconds * the caller wants to check param fn(); * reject() the promise at the expiration of param timeout. * @param {number} interval - minimum number of milliseconds between * calls to param fn(); resolve() the promise when param fn() first * reports true. * @return {promise} - resolved when param fn() returns true; * rejected if param timeout expires without param fn() returning true */ function poll(fn, timeout, interval) { let endTime = Number(new Date()) + (timeout || 2000) interval = interval || 250 return Promise.resolve *2 .then(() => { *3 (function p(fn, endTime, interval) { if (fn()) { return Promise.resolve("Condition is satisfied.") } *4 else { if (Number(new Date()) <= endTime) {) *5 window.setTimout(p, interval, fn, endTime, interval) *6 } else { return Promise.reject("Past endTime; condition not satisfied") } } }()) *7 }) *8 } 后,我们会立即在* 2处返回待处理的承诺,以便function waitIsOver() { return (<desired condition exists>) } poll(waitIsOver, 2000, 250) *1 知道等。然后,我们将该承诺的poll()函数称为* 3。函数poll()开始。如果then()(在p()以外称为fn())在* 4返回true,我们就会很好:我们返回p(),而waitIsOver()在* 1获取它所寻求的坚定承诺。

然后是不好的部分:如果resolve()在* 4返回false而我们在* {5}内{(1}}(很可能; poll()之后不太可能发生第一次调用),我们在* 6使用fn()要求JS在堆栈中做一个注释,以便在endTime时间后实例化另一个endTime。之后,setTimeout()的第一个实例终止于* 7。在* 8,p()知道interval在没有返回任何内容的情况下终止,并将条件解释为返回p()then();与p()一起,承诺得以解决,永远不会改变。但是,false到期后,reject()的后续实例会启动。它返回的任何东西都会丢失;承诺得到解决,reject()在不需要的路径上发送执行后终止。

How do I convert an existing callback API to promises?推荐使用Promise构造函数的方法,interval调用p()then()调用resolve()。我尝试了这种技术,但是在遇到问题之前我遇到了callback()函数结束的相同问题。我还没有弄清楚如何让reject()作为耐心等待作为回调函数。

这就提出了问题。再次:

问题:如何最好地帮助errback功能,以便以后从then()then()返回?

2 个答案:

答案 0 :(得分:4)

  

如何最好地帮助.then()函数留下来以便以后返回   来自resolve()或reject()

在解决或拒绝基础承诺时调用.then()处理程序。永远不会在此之前调用它。因此,如果您想在调用.then()处理程序时延迟,那么您将延迟解析或拒绝基础承诺,直到适当的时间。

正如你从我的评论中可以看出的那样,很难准确地说出你想要完成什么,因为你不仅仅描述了你想要实现的直接目标。

鉴于此,我猜你想要完成的是什么。一个明确的问题可能会在几分钟内得到这样的答案。

如果您只是想重复轮询您的函数,直到它返回真值或直到超时时间到达,您可以使用标准的ES6承诺执行此操作:

function poll(fn, timeout, interval) {
    return new Promise(function(resolve, reject) {
        // set timeout timer
        var timeoutTimer = setTimeout(function() {
            clearInterval(intervalTimer);
            reject("Past endTime; condition not satisfied");
        }, timeout);

        // set polling timer
        var intervalTimer = setInterval(function() {
            if (fn()) {
                clearTimeout(timeoutTimer);
                clearInterval(intervalTimer);
                resolve("Condition is satisfied");
            }
        }, interval);
    });
}

poll(yourFounction, 5000, 100).then(function(result) {
    // succeeded here
}).catch(function(err) {
    // timed out here
})

或者,使用Bluebird promise库,您可以使用其.timeout()方法执行此操作:

function poll(fn, timeout, interval) {
    return new Promise(function(resolve, reject) {
        // set polling timer
        var intervalTimer = setInterval(function() {
            if (fn()) {
                clearInterval(intervalTimer);
                resolve("Condition is satisfied");
            }
        }, interval);
    }).timeout(timeout, "Past endTime; condition not satisfied");
}

poll(yourFounction, 5000, 100).then(function(result) {
    // succeeded here
}).catch(function(err) {
    // timed out here
})

请注意,这两个方案都返回一个promise,然后当poll()函数完成时,它们会调用resolve或拒绝新的promise,然后触发任何.then()个处理程序被调用。

P.S。我应该补充一点,这一切都假设你的fn()是一个同步函数,它返回一个真值或假值(这是你的代码似乎假设的)。如果您的fn()实际上是具有回调或承诺的异步函数,则需要将其考虑在设计中。在编写正确使用的代码之前,您必须向我们展示函数的调用约定。

答案 1 :(得分:2)

既然你说你发现有回调的轮询功能,这基本上归结为&#34;我如何宣传某些内容?&#34;

使用BluebirdJS的Promisify:

var poleYouFoundThatHasCallback = require('somePollLibrary');
var Promise = require('bluebird');
var poll = Promise.Promisify(poleYouFoundThatHasCallback);

poll.then((res) => { 
//dostuff with res here

}).catch(err => console.log(err))

你也可以为它施加超时和傻笑。

来自docs的示例和示例:

var Promise = require("bluebird");
var fs = Promise.promisifyAll(require('fs'));
fs.readFileAsync("huge-file.txt").timeout(100).then(function(fileContents) {

}).catch(Promise.TimeoutError, function(e) {
    console.log("could not read file within 100ms");
});