我正在尝试将我的一些代码转换为承诺,但我无法弄清楚如何在承诺中链接新的承诺。
我的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);
});
显然它不起作用,什么都没有打印
答案 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
函数。
解决方案:
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);
});