循环承诺!如何?
Promise in a loop! How to?
一段时间以来,我一直在尝试让这段代码工作,但我似乎就是做不到。它用于实时更新图,每个点都包含一个 [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()
试图从 JSON
构建一个 X = timestamp.now()
和 Y = "Value"
的数组,然后将该数组推入我的 "overall"
数据数组。
这样做会使 value
成为 [<timestamp>, Unresolved]
.
的数组
这样做:
while (data.length < totalPoints) {
getZScoreData().then(function (result) {
var valueArray = [now += updateInterval, result];
data.push(valueArray);
});
};
使 valueArray
成为实际的 [<timestamp>, <JSON "value"]
,如果我 console.log(value)
,除了这种方式似乎永远挂起服务器并为选项卡消耗大量 RAM,就好像我正在做一个无限循环(数百个对 Web 服务器的获取请求,即使最大长度应该是 100)。不过,我不确定 Promise 内部发生了什么以获得这种行为。
这是在示例中运行的代码:
while (data.length < totalPoints) {
var y = Math.random() * 100;
var value = [now += updateInterval, y];
data.push(value);
};
看起来很简单。它说 y (in var value = [now += updateInterval, y];
) make "y" get the value from my API.
我不知道如何真正做到这一点。
我正在按照 this Flot example 中的示例进行操作,但我无法使其与 AJAX 或 Promise 中的实际实时值一起使用(我什至尝试过获取)。
"live updating table" 的所有示例最终都只使用了 math.random()
,这是非常具有误导性的,因为它只是有点移动,但并不是真的存在。
我相信我没有正确解决循环中的承诺,但由于缺乏经验,此时我什至不确定哪里出了问题。
我不确定在我的代码中我会去哪里 Y = "live value"
,或者我是否必须 return 在某个地方产生结果?我不太熟悉 Promises 或 AJAX。
循环中的 Promise 很少是个好主意,您通常会希望使用 Promise.all()
一次执行多个 Promise,并将它们的结果收集在一个数组中:
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 有一些关于 Promises 的好材料:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Using_promises
附带说明一下,即使使用 Promise.all()
,同时执行 100 个 AJAX 请求听起来也很吃力。如果您对后端有任何影响,您应该尝试优化后端,或者查看 Worker
s 以批量执行请求。
您可以生成 Promise 数组,然后使用 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
没有达到 return 声明,因为它
到达 Promise.resolve
后立即解析。 (在我的例子中,
现在 getData
return 是一个承诺)
- 使用
Promise.all
这样你就不用等了
在执行下一个之前完成前一个......它
一旦突袭中的每一个承诺都解决了,或者其中之一解决了
失败(你必须.catch
那个)。
- 详细了解 Promises, they are scary at first, but you'll end up loving em
试试这个代码,它可能无法工作,因为我没有完整的工作示例,但你可能会绕过错误并让它工作。
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)
};
一段时间以来,我一直在尝试让这段代码工作,但我似乎就是做不到。它用于实时更新图,每个点都包含一个 [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()
试图从 JSON
构建一个 X = timestamp.now()
和 Y = "Value"
的数组,然后将该数组推入我的 "overall"
数据数组。
这样做会使 value
成为 [<timestamp>, Unresolved]
.
这样做:
while (data.length < totalPoints) {
getZScoreData().then(function (result) {
var valueArray = [now += updateInterval, result];
data.push(valueArray);
});
};
使 valueArray
成为实际的 [<timestamp>, <JSON "value"]
,如果我 console.log(value)
,除了这种方式似乎永远挂起服务器并为选项卡消耗大量 RAM,就好像我正在做一个无限循环(数百个对 Web 服务器的获取请求,即使最大长度应该是 100)。不过,我不确定 Promise 内部发生了什么以获得这种行为。
这是在示例中运行的代码:
while (data.length < totalPoints) {
var y = Math.random() * 100;
var value = [now += updateInterval, y];
data.push(value);
};
看起来很简单。它说 y (in var value = [now += updateInterval, y];
) make "y" get the value from my API.
我不知道如何真正做到这一点。
我正在按照 this Flot example 中的示例进行操作,但我无法使其与 AJAX 或 Promise 中的实际实时值一起使用(我什至尝试过获取)。
"live updating table" 的所有示例最终都只使用了 math.random()
,这是非常具有误导性的,因为它只是有点移动,但并不是真的存在。
我相信我没有正确解决循环中的承诺,但由于缺乏经验,此时我什至不确定哪里出了问题。
我不确定在我的代码中我会去哪里 Y = "live value"
,或者我是否必须 return 在某个地方产生结果?我不太熟悉 Promises 或 AJAX。
循环中的 Promise 很少是个好主意,您通常会希望使用 Promise.all()
一次执行多个 Promise,并将它们的结果收集在一个数组中:
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 有一些关于 Promises 的好材料:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Using_promises
附带说明一下,即使使用 Promise.all()
,同时执行 100 个 AJAX 请求听起来也很吃力。如果您对后端有任何影响,您应该尝试优化后端,或者查看 Worker
s 以批量执行请求。
您可以生成 Promise 数组,然后使用 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
没有达到 return 声明,因为它 到达Promise.resolve
后立即解析。 (在我的例子中, 现在getData
return 是一个承诺) - 使用
Promise.all
这样你就不用等了 在执行下一个之前完成前一个......它 一旦突袭中的每一个承诺都解决了,或者其中之一解决了 失败(你必须.catch
那个)。 - 详细了解 Promises, they are scary at first, but you'll end up loving em
试试这个代码,它可能无法工作,因为我没有完整的工作示例,但你可能会绕过错误并让它工作。
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)
};