ES6承诺具有超时间隔

时间:2017-10-29 18:34:14

标签: javascript node.js promise

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

我的promise函数应该每隔一秒左右检查一个数组的内容,如果里面有任何项目应该解决。否则它应等待1秒并再次检查,依此类推。

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()promise函数工作的方式,它应该在最多2或3秒后打印“test”:

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

显然它不起作用,什么都没有打印

6 个答案:

答案 0 :(得分:2)

问题在于,您的递归调用并未通过resolve函数,因此else分支永远不会调用resolve

解决此问题的一种方法是在promise的回调中创建一个闭包,以便递归调用可以访问与resolve的初始调用相同的get变量。



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));




答案 1 :(得分:2)

setTimeout本身具有可怕的链接和错误处理特性,所以始终wrap it

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'));

虽然你没有问,为了别人的利益,async / await闪耀的是一个很好的案例:

const wait = ms => new Promise(r => setTimeout(r, ms));

async function get(c) {
  while (!c.length) {
    await wait(1000);
  }
  return c.shift();
}

let c = [];
get(c).then(val => console.log(val));
wait(2000).then(() => c.push('test'));

请注意我们这次不需要Promise.resolve(),因为async函数会隐式执行此操作。

答案 2 :(得分:0)

else案例中,您永远不会解决 承诺。 get可能会创建另一个,但它无处可归。

您应该promisify最低级别的异步函数(setTimeout),然后只链接您的承诺。通过{{1}来自return回调的递归调用的结果,生成的promise将以相同的结果解析:

then

答案 3 :(得分:0)

您需要的是一个轮询服务,它会在继续进行承诺解决之前定期检查特定情况。目前,当您运行setTimeout(get.bind(this), 1000);时,您正在创建承诺的新实例,而不实际解析初始承诺,因为您没有引用您创建的初始resolve函数。

解决方案:

  • 创建一个新的回调函数,您可以在promise
  • 中引用它
  • 通过resolve& reject作为setTimeout调用中的params,例如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);
});

答案 4 :(得分:0)

您可以尝试此解决方案。由于JS需要释放自身来下载图像,因此我在异步函数和异步调用中使用await在延迟后唤醒JS

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.cm import get_cmap
from netCDF4 import Dataset
from wrf import to_np, getvar, smooth2d, get_basemap, latlon_coords, interplevel

from netCDF4 import Dataset
ncfile = Dataset("wrfout_d01_2019-12-30_00_00_00")
T=getvar(ncfile, "T2")
max_T = np.max(T)

lev=np.arange(290,306,2)

for time in range (0,25):
xx = int(time)
T = getvar(ncfile, "T2",xx)

# Smooth the sea level pressure since it tends to be noisy near the mountains
smooth_tc = smooth2d(T, 3)

# Get the latitude and longitude points
lats, lons = latlon_coords(T)

# Get the basemap object
bm = get_basemap(T)

# Create a figure
fig = plt.figure(figsize=(12,9))

# Add geographic outlines
bm.drawcoastlines(linewidth=3)
bm.drawstates(linewidth=3)
bm.drawcountries(linewidth=3)

# Convert the lats and lons to x and y.  Make sure you convert the lats and lons to
# numpy arrays via to_np, or basemap crashes with an undefined RuntimeError.
x, y = bm(to_np(lons), to_np(lats))

# Draw the contours and filled contours
CS = bm.contour(x, y, to_np(smooth_tc), 9,colors="black")
plt.clabel(CS, inline=1, fontsize=10)
bm.contourf(x, y, to_np(smooth_tc), 9, cmap=get_cmap("inferno"))

# Add a color bar
plt.colorbar(shrink=.62)
plt.title("Temperature (K) - T" + str(xx))
plt.show()

#fig.savefig('d01_PSFC_'+str(xx) +'.png')

答案 5 :(得分:-1)

使用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);
});