循环承诺!如何?



我一直在尝试让这段代码工作一段时间,但我似乎无法理解它。它用于实时更新图,每个点接收一个 [x, y] 的数组,因此是一个数组数组。

输入是来自服务器的JSON列表,该列表更新相同的JSON对象(因此它更改一个JSON并仅更新值(:

[
{
"Value": 10,
"Name": "Name of variable"
}
]

我只需要提取值。

我是这样试过的:

var getValueData = async function() {
var valueJSON = await Promise.resolve($.getJSON( "{% url 'get_value' %}" ));
return valueJSON[0]['Value'];
};
var data = [];
var totalPoints = 100;
var updateInterval = 1000;
var now = new Date().getTime();
function getData() {
data.shift();
while (data.length < totalPoints) {
var value = [now += updateInterval,
getValueData().then(function(result) {
result;
})
];
data.push(value);
};
};

基本上,getData()正在尝试构建一个X = timestamp.now()数组,Y从JSON= "Value",然后将该数组推送到我的"overall"数据数组中。

这样做会使value成为[<timestamp>, Unresolved]数组。

这样做:

while (data.length < totalPoints) {
getZScoreData().then(function (result) {
var valueArray = [now += updateInterval, result];
data.push(valueArray);
});
};

如果我console.log(value)valueArray成为一个实际的[<timestamp>, <JSON "value"],除了这种方式似乎永远挂起服务器并为选项卡消耗大量 RAM,就好像我在做一个无限循环(数百个对 Web 服务器的 get 请求,即使最大长度应该为 100(。不过,我不确定 Promise 内部发生了什么来获得这种行为。

这是在示例中工作的代码:

while (data.length < totalPoints) {     
var y = Math.random() * 100;
var value = [now += updateInterval, y];
data.push(value);
};

这似乎很简单。如果它说 y(在var value = [now += updateInterval, y];中(,则使"y"从我的 API 中获取值。

我不知道如何实际实现这一目标。

我正在遵循这个 Flot 示例中的示例,但我无法使其与来自 AJAX 或 Promise 的实际实时值一起工作(我什至尝试过获取(。

"实时更新表"的所有示例最终都只使用了math.random(),这是非常具有误导性的,因为它只是有点移动,但并不是真正的实时。

我相信我没有正确解决循环中的承诺,但由于缺乏经验,在这一点上我什至不确定出了什么问题。

我不确定我会在我的代码中Y = "live value"哪里,或者我是否必须在某处返回结果?我对Promises或AJAX不太熟悉。

循环中的承诺很少是一个好主意,你通常需要使用Promise.all()一次执行多个承诺,并将它们的结果收集到一个数组中:

function getData() {
// Note: Why is this here?
data.shift();
var promises = [];
while (data.length < totalPoints) {
promises.push(getValueData());
}
Promise.all(promises).then(results => {
for (let result of results) {
var value = [
now += updateInterval,
result
];
data.push(value);
}
});
};

MDN有一些关于承诺的好材料:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Using_promises

作为旁注,同时执行 100 个 AJAX 请求听起来非常费力,即使有Promise.all().如果您对后端有任何影响,您应该尝试优化后端,或者查看Worker以批量执行请求。

您可以生成承诺数组,然后等待Promise.all解决。

// Let's imitate some async operation
// It is instead of your getValueData
function twiceAsync(a) {
// returns a promise resolving to twice argument
return new Promise(function(ok) {
setTimeout(function(){ok(2*a)}, 100);
});
}
var pList = [];
for (var i = 0; i < 100; ++i) {
// collect promises returned by twiceAsync to an array
pList.push(twiceAsync(i));
}
Promise.all(pList) // provide array of promises to Promise.all
.then(function(results) { // receive resolved results, they should be even numbers from 0*2 to 99*2
console.log(results);
})

你应该记住的一些事情

  • 您的getValueData未到达返回语句,因为它 到达Promise.resolve后立即解决。(在我的示例中, 现在getData返回一个承诺(
  • 使用Promise.all,这样您就不会等待 在执行下一个之前完成上一个...它 在 RAID 中的每个承诺解决后解决,或其中一个承诺 失败(你必须.catch(。
  • 了解更多关于承诺的信息,它们一开始很可怕,但你最终会爱上它们

试试这段代码,它可能不起作用,因为我没有完整的工作示例,但你可以绕过错误并让它工作。

var results = [],
totalPoints = 100,
pointsLeft = totalPoints, // since we are using Promise.all, now we have to track this instead of results.length
updateInterval = 1000,
promises = [],
getValueData = async function(timestamp) {
await $.getJSON('yourURL').done(function (data) {
pointsLeft-- // promise fulfilled 
Promise.resolve({ data, timestamp })
}).fail(Promise.reject)
};
function getData() {
// results.shift(); why?
while (pointsLeft) {
// push the promise to the stack, collect them later
promises.push(getValueData(Date.now()))
};

Promise.all(promises).then(function (responses) {
responses.forEach(function (data, timestamp) {
results.push([timestamp, data])
})
}).catch(console.warn)
};

最新更新