简体   繁体   English

如何在循环中同步then()

[英]How to synchronise then() inside for loop

I am facing problem while calling a then() function inside for loop here is my below code 我在for循环内调用then()函数时遇到问题,这是我的以下代码

The chunk of code 代码块

StretchData.getById(item).then(function (data) 

Is calling after j==3 but my requirement it should call each iteration Any idea how to achieve this.I tried many things still no result. 在j == 3之后调用,但我的要求是每次迭代都要调用任何想法如何实现这一点。我尝试了很多事情仍然没有结果。

for (var j = 0; j < 3; j++) {

                StretchData.getById(item)
                .then(function (data) {
                    alert(startWorkOutModel.sortValue);
                    startWorkOutModel.inStretchedData = {
                        sort: startWorkOutModel.sortValue,
                        sData: data.result
                    }
                    startWorkOutModel.stretchedData.push(startWorkOutModel.inStretchedData);
                    fl = true;
                    console.log(JSON.stringify(startWorkOutModel.stretchedData));
                    // break;

                },
                function (error) {
                    alert(JSON.stringify(error));
                });                            

      }

When you have a loop or array that you need to process asynchronously in parallel, you build up an array of the promises returned by then and then wait for them all using Promise.all . 当您有一个需要并行并行处理的循环或数组时,可以构建一个由then返回的promise组成的数组,然后使用Promise.all等待它们全部Promise.all You'd also normally handle errors on the promise from Promise.all rather than individually, unless you're able to do error-correction and return something to use instead of the error. 通常,您还应处理Promise.all承诺中的错误,而不是单独处理,除非您能够进行错误纠正并返回要使用的内容而不是错误。

Something along these lines: 这些方针的东西

var promises = [];
for (var j = 0; j < 3; j++) {
    promises.push(
        StretchData.getById(item)
            .then(function(data) {
                // *** Gets called for each individual item
                alert(startWorkOutModel.sortValue);
                startWorkOutModel.inStretchedData = {
                    sort: startWorkOutModel.sortValue,
                    sData: data.result
                }
                startWorkOutModel.stretchedData.push(startWorkOutModel.inStretchedData);
                fl = true;
                console.log(JSON.stringify(startWorkOutModel.stretchedData));

                // *** Normally you'd want to return something here
            })
    );
}
Promise.all(promises)
    .then(
        function(results) {
            // *** Use results (an array of the promise results) here
        },
        function(error) {
            // *** At least one promise failed
        }
    );

As I mentioned in a comment on the question, you're not using j within the loop, so that does the same exact thing three times in a row. 正如我在对问题的评论中提到的那样,您没有在循环中使用j ,因此连续三遍执行相同的操作。 If you needed to use j in the promise callback code, you have two options: 如果需要在promise回调代码中使用j ,则有两个选择:

ES5 and earlier ES5及更早版本

Use a function to capture the value of j into an unchanging variable the callback can use (since j will be 3 by the time any of those callbacks runs): 使用一个函数将j的值捕获到回调可以使用的不变变量中(因为当这些回调中的任何一个运行时j将为3 ):

function doRequestFor(value) {
    return StretchData.getById(item)
            .then(function(data) {
                // *** Gets called for each individual item
                // *** Use `value` here (in place of `j`)
                alert(startWorkOutModel.sortValue);
                startWorkOutModel.inStretchedData = {
                    sort: startWorkOutModel.sortValue,
                    sData: data.result
                }
                startWorkOutModel.stretchedData.push(startWorkOutModel.inStretchedData);
                fl = true;
                console.log(JSON.stringify(startWorkOutModel.stretchedData));

                // *** Normally you'd want to return something here
            });
}
var promises = [];
for (var j = 0; j < 3; j++) {
    promises.push(getRequestFor(j));
}
Promise.all(promises)
    .then(
        function(results) {
            // *** Use results here
        },
        function(error) {
            // *** At least one promise failed
        }
    );

ES2015 (aka "ES6") and later ES2015(又名“ ES6”)及更高版本

You can make use of let 's handling in for loops which means each loop iteration gets its own copy of j : 您可以在for循环中使用let的处理方式,这意味着每次循环迭代都获得自己j副本:

let promises = [];
for (let j = 0; j < 3; j++) {
//   ^^^---------------------------- *** Note
    promises.push(
        StretchData.getById(item)
            .then(function(data) {
                // *** Gets called for each individual item
                // *** Use `j` here, it'll be 0, 1, or 2
                alert(startWorkOutModel.sortValue);
                startWorkOutModel.inStretchedData = {
                    sort: startWorkOutModel.sortValue,
                    sData: data.result
                }
                startWorkOutModel.stretchedData.push(startWorkOutModel.inStretchedData);
                fl = true;
                console.log(JSON.stringify(startWorkOutModel.stretchedData));

                // *** Normally you'd want to return something here
            })
    );
}
Promise.all(promises)
    .then(
        function(results) {
            // *** Use results (an array of the promise results) here
        },
        function(error) {
            // *** At least one promise failed
        }
    );

First of all. 首先。 Variables declared with var in JavaScript are function-scoped and not block scoped which means (because the callback is asynchronous) that j will be 3 in all callback executions. JavaScript中用var声明的变量是函数作用域的,而不是块作用域的,这意味着(因为回调是异步的),在所有回调执行中j将为3。 You can get around that fact by declaring the variable j with let which instead block scopes it. 您可以通过使用let声明变量j解决这个问题,而使用block来限制范围。

for (let j = 0; ...

Second. 第二。 Is it important that the callbacks are run in series? 回调顺序运行是否重要? In that case you will have to refactor your code considerably. 在这种情况下,您将不得不大量重构代码。 Maybe making the call recursive and chain the next call of the loop to the callback of the first. 也许使调用递归,并将循环的下一个调用链接到第一个的回调。

If not, but it is still important that you can act when all callbacks are completed, you can store the deferreds in a list and pass them to Promise.all(yourDeferredList) which will callback when all are completed. 如果不是,但是在所有回调完成时可以采取行动仍然很重要,您可以将这些延迟存储在列表中,并将它们传递给Promise.all(yourDeferredList) ,后者将在所有回调完成后进行回调。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM