ES6承诺超时间隔

我试图将我的一些代码转换为承诺,但我无法弄清楚如何在承诺中链接一个新的承诺。

我的承诺函数应该每隔一秒左右检查一次数组的内容,如果里面有任何项目应该解决。 否则,应该等待1s再次检查,等等。

function get(){ return new Promise((resolve) => { if(c.length > 0){ resolve(c.shift()); }else{ setTimeout(get.bind(this), 1000); } }); } let c = []; setTimeout(function(){ c.push('test'); }, 2000); 

这是我期望我的get()承诺函数工作,它应该打印“testing”最多2或3秒后:

 get().then((value) => { console.log(value); }); 

显然这不起作用,什么也不打印

问题是您的recursion调用不会传递resolve函数,所以else分支永远不能调用resolve

解决这个问题的一种方法是在promise的callback中创build一个闭包,这样recursion调用将获得与初始调用get相同的resolvevariables。

 function get() { return new Promise((resolve) => { function loop() { if (c.length > 0) { resolve(c.shift()); } else { setTimeout(loop, 1000); } } loop(); }); } let c = []; setTimeout(function() { c.push('test'); }, 2000); get().then(val => console.log(val)); 

setTimeout本身具有可怕的链接和error handling特性,所以总是包装它 :

 const wait = ms => new Promise(resolve => setTimeout(resolve, ms)); function get(c) { if (c.length) { return Promise.resolve(c.shift()); } return wait(1000).then(() => get(c)); // try again } let c = []; get(c).then(val => console.log(val)); wait(2000).then(() => c.push('test')); 

使用setInterval检查每一秒。 运行这个脚本来理解。

 let c = []; function get(){ return new Promise((resolve) => { var i = setInterval(function(){ if(c.length > 0){ resolve(c.shift()); clearInterval(i); } }, 1000); }); } setTimeout(function(){ c.push('test'); }, 2000); get().then((value) => { console.log(value); }); 

else情况下,你永远不会解决这个承诺。 get可能创造另一个,但它被返回到无处。

您应该在最低级别上提供asynchronous函数( setTimeout ),然后只链接您的承诺。 通过从callback中returnrecursion调用的结果,所得到的承诺将以相同的结果解决:

 function delayAsync(time) { return new Promise(resolve => { setTimeout(resolve, time); }); } function get(c) { if (c.length > 0){ return Promise.resolve(c.shift()); } else { return delay(1000).then(() => { return get(c); // try again }); } } 

您需要的是一个轮询服务,在进行承诺解决之前,该服务会定期检查特定条件。 目前当你运行setTimeout(get.bind(this), 1000); 您正在创build承诺的新实例,而不实际解决最初的承诺,因为您不参考您创build的初始resolve函数。

解:

  • 创build一个新的callback函数,您可以在promise中引用它
  • 在setTimeout调用中传递resolvereject作为参数,例如setTimeout(HandlePromise, 1000, resolve, reject, param3, param4 ..); setTimeout API
 function get() { var handlerFunction = resolve => { if (c.length > 0) { resolve(c.shift()); } else { setTimeout(handlerFunction, 1000, resolve); } }; return new Promise(handlerFunction); } let c = []; setTimeout(function() { c.push("test"); }, 2000); get().then(value => { console.log(value); });