将 promise 的结果推入数组
Pushing result from promise into array
我正在尝试清空数组,然后使用承诺返回的值重新填充数组。但是,当我这样做时,并不总是以相同的顺序将它们添加回去。
$scope.$watch ('timeRange', function (newValue, oldValue, scope){
$scope.chartdata = []
//If a filter has changed, redraw all charts
if (newValue !== oldValue)
{
for(var i = 0; i< $scope.charts.length; i++){
$scope.draw($scope.charts[i]).then(function(value){
$scope.chartdata.push(value);
});
}
}
}, true);
这是用 ng-repeat 显示的。
由于您正在异步执行操作,因此可能无法保证解析顺序。您可以使用索引 i
而不是 push
$scope.$watch ('timeRange', function (newValue, oldValue, scope){
$scope.chartdata = []
//If a filter has changed, redraw all charts
if (newValue !== oldValue)
{
for(var i = 0; i< $scope.charts.length; i++){
$scope.draw($scope.charts[i]).then(function(i) { // create scope to capture i
return function(value) { $scope.chartdata[i] = value; };
}(i));
}
}
}, true);
UPD 添加的示例只是为了演示@georgeawg 作用域的工作原理
var arr = [1, 2, 3];
for (var i = 0; i < arr.length; i++) {
setTimeout(function(i) {
return function() {
console.log(`Let's teach @georgeawg scopes ${i}`)
}
}(i), i * 1000)
}
或使用forEach
$scope.$watch ('timeRange', function (newValue, oldValue, scope){
$scope.chartdata = []
//If a filter has changed, redraw all charts
if (newValue !== oldValue)
{
$scope.charts.forEach(function(chart, i) {
$scope.draw(chart).then(function(value) {
$scope.chartdata[i] = value;
})
})
}
}, true);
或使用 Promise.all
或其 angularjs 模拟 $q.all
.
一次添加所有
$scope.$watch ('timeRange', function (newValue, oldValue, scope){
$scope.chartdata = []
//If a filter has changed, redraw all charts
if (newValue !== oldValue)
{
$q.all($scope.charts.map(function(chart) {
return $scope.draw(chart)
}).then(function(chartdata) {
$scope.chartdata = chartdata;
})
}
}, true);
有错误的代码段
function randInt(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
function asyncFunc(index) {
return new Promise((resolve) => {
setTimeout(() => resolve(index), randInt(0, 3000));
});
}
const results = [];
for (var i = 0; i < 5; i++) {
asyncFunc(i)
.then((ret) => {
results.push(ret);
});
}
setTimeout(() => {
console.log(results);
}, 4000);
带有解决方案的代码段
我们可以在 IEFF
函数中传递数据的位置。
function randInt(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
function asyncFunc(index) {
return new Promise((resolve) => {
setTimeout(() => resolve(index), randInt(0, 3000));
});
}
const results = [];
for (var i = 0; i < 5; i++) {
(function(j) {
asyncFunc(i)
.then((ret) => {
results[j] = ret;
});
})(i);
}
setTimeout(() => {
console.log(results);
}, 4000);
一个简单的方法是使用 .map
和 Promise.all
(或 AngularJS 中的 $q.all()
)。这将保持项目的顺序,作为一个额外的好处,允许您检测何时填充了整个数组。
借用 Gregory 的回答中的示例代码:
(注意:下面使用了setTimeout
、new Promise
和Promise.all
来提供一个简单的说明性演示作为可运行的 Stack Snippet。在实际的 AngularJS 代码中,您不需要 setTimeout
或 new Promise
,您应该使用 $q.all
而不是 Promise.all
,因为如最后的示例所示)
function randInt(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
function delay(ms) {
return new Promise(function (resolve) { setTimeout(resolve, ms); });
}
function asyncFunc(value) {
return delay(randInt(0, 3000))
.then(function () {
console.log(value, 'finished');
return value * 2 + 1;
});
}
const origArray = [0, 1, 2, 3, 4];
Promise.all(origArray.map(asyncFunc))
.then(function (resultArray) {
console.log(resultArray);
});
将其应用于您的特定代码,我们将:
$scope.$watch ('timeRange', function (newValue, oldValue, scope){
$scope.chartdata = []
//If a filter has changed, redraw all charts
if (newValue !== oldValue)
{
$q.all($scope.charts.map($scope.draw))
.then(function (resultArray) {
$scope.charts = resultArray;
});
}
}, true);
我正在尝试清空数组,然后使用承诺返回的值重新填充数组。但是,当我这样做时,并不总是以相同的顺序将它们添加回去。
$scope.$watch ('timeRange', function (newValue, oldValue, scope){
$scope.chartdata = []
//If a filter has changed, redraw all charts
if (newValue !== oldValue)
{
for(var i = 0; i< $scope.charts.length; i++){
$scope.draw($scope.charts[i]).then(function(value){
$scope.chartdata.push(value);
});
}
}
}, true);
这是用 ng-repeat 显示的。
由于您正在异步执行操作,因此可能无法保证解析顺序。您可以使用索引 i
而不是 push
$scope.$watch ('timeRange', function (newValue, oldValue, scope){
$scope.chartdata = []
//If a filter has changed, redraw all charts
if (newValue !== oldValue)
{
for(var i = 0; i< $scope.charts.length; i++){
$scope.draw($scope.charts[i]).then(function(i) { // create scope to capture i
return function(value) { $scope.chartdata[i] = value; };
}(i));
}
}
}, true);
UPD 添加的示例只是为了演示@georgeawg 作用域的工作原理
var arr = [1, 2, 3];
for (var i = 0; i < arr.length; i++) {
setTimeout(function(i) {
return function() {
console.log(`Let's teach @georgeawg scopes ${i}`)
}
}(i), i * 1000)
}
或使用forEach
$scope.$watch ('timeRange', function (newValue, oldValue, scope){
$scope.chartdata = []
//If a filter has changed, redraw all charts
if (newValue !== oldValue)
{
$scope.charts.forEach(function(chart, i) {
$scope.draw(chart).then(function(value) {
$scope.chartdata[i] = value;
})
})
}
}, true);
或使用 Promise.all
或其 angularjs 模拟 $q.all
.
$scope.$watch ('timeRange', function (newValue, oldValue, scope){
$scope.chartdata = []
//If a filter has changed, redraw all charts
if (newValue !== oldValue)
{
$q.all($scope.charts.map(function(chart) {
return $scope.draw(chart)
}).then(function(chartdata) {
$scope.chartdata = chartdata;
})
}
}, true);
有错误的代码段
function randInt(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
function asyncFunc(index) {
return new Promise((resolve) => {
setTimeout(() => resolve(index), randInt(0, 3000));
});
}
const results = [];
for (var i = 0; i < 5; i++) {
asyncFunc(i)
.then((ret) => {
results.push(ret);
});
}
setTimeout(() => {
console.log(results);
}, 4000);
带有解决方案的代码段
我们可以在 IEFF
函数中传递数据的位置。
function randInt(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
function asyncFunc(index) {
return new Promise((resolve) => {
setTimeout(() => resolve(index), randInt(0, 3000));
});
}
const results = [];
for (var i = 0; i < 5; i++) {
(function(j) {
asyncFunc(i)
.then((ret) => {
results[j] = ret;
});
})(i);
}
setTimeout(() => {
console.log(results);
}, 4000);
一个简单的方法是使用 .map
和 Promise.all
(或 AngularJS 中的 $q.all()
)。这将保持项目的顺序,作为一个额外的好处,允许您检测何时填充了整个数组。
借用 Gregory 的回答中的示例代码:
(注意:下面使用了setTimeout
、new Promise
和Promise.all
来提供一个简单的说明性演示作为可运行的 Stack Snippet。在实际的 AngularJS 代码中,您不需要 setTimeout
或 new Promise
,您应该使用 $q.all
而不是 Promise.all
,因为如最后的示例所示)
function randInt(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
function delay(ms) {
return new Promise(function (resolve) { setTimeout(resolve, ms); });
}
function asyncFunc(value) {
return delay(randInt(0, 3000))
.then(function () {
console.log(value, 'finished');
return value * 2 + 1;
});
}
const origArray = [0, 1, 2, 3, 4];
Promise.all(origArray.map(asyncFunc))
.then(function (resultArray) {
console.log(resultArray);
});
将其应用于您的特定代码,我们将:
$scope.$watch ('timeRange', function (newValue, oldValue, scope){
$scope.chartdata = []
//If a filter has changed, redraw all charts
if (newValue !== oldValue)
{
$q.all($scope.charts.map($scope.draw))
.then(function (resultArray) {
$scope.charts = resultArray;
});
}
}, true);