简体   繁体   English

如何在循环的每次迭代中执行 promise.then? Javascript

[英]How to execute promise.then in each iteration of loop? Javascript

I'm having an issue with a promise inside a loop.我在循环中遇到了 promise 的问题。 I have 10000 rows in databse, and I wanna print first 1000 rows and then, fetch 9 requests to print the rest.我在数据库中有 10000 行,我想打印前 1000 行,然后获取 9 个请求来打印 rest。 Technically, I want to print the 1000 results on each iteration of loop, for that, I'm using a promise for get the data, and.THEN create 1000 rows and print it.从技术上讲,我想在循环的每次迭代中打印 1000 个结果,为此,我使用 promise 来获取数据,然后创建 1000 行并打印它。

But the problem is that first JavaScript's loops get's the 10 requests and then, execute the 10.THEN together.但问题是,首先 JavaScript 的循环获取 10 个请求,然后一起执行 10.THEN。

I mean:我是说:

1000 results  (First loop)
2000 results (Second loop) - Append 1000 new rows to last 1000.
3000 results (Third loop) - Append 1000 new rows to last 2000.
....

What I obtain:我得到的:

Console.logs 示例

In the last image, "first for loop" are getting 10 requests and, when the loop finishes, .THEN print each promise callback (.THEN)在最后一张图片中,“第一个 for 循环”收到 10 个请求,当循环完成时,.THEN 打印每个 promise 回调 (.THEN)

That's my code:那是我的代码:

fetchData('ArticulosSearch', inputValues).then(function (data) {
        console.log(data);
        var source = getGridSource(url, datafields, "array", data);
        // Creamos el grid con las primeras 1000 rows obtenidas
        $("#GridAseguradora").createGrid(source, dataColumns, params);

        //Obtenemos el nº de registros que tiene la bbdd para calcular cuantas peticiones debe hacer
        setTimeout(() => {
            fetchData('ArticulosSearchCount', inputValues).then(function (total_rows) {
                console.log("count");
                console.log(total_rows);
                var filt = (total_rows[0].Column1 / 1000) //pagines - peticiones
                console.log(filt);

                // Creamos promesa para añadir posteriormente las filas al grid una vez hayan terminado todas las peticiones
                for (var i = 1; i < filt; i++) {
                    (function (i) {
                        console.log("first for loop");
                        inputValues.offset = (1000 * i)
                        fetchData('ArticulosSearch', inputValues).then(function (data) {  //Obtenemos las 1000 siguientes filas y las añadimos a un array
                            console.log("obtain 1000 results");
                            console.log(data);
                            var rows = new Array();

                            data.forEach(el => {
                                rows.push(generaterow(el))
                            });

                            $("#GridAseguradora").jqxGrid('addrow', null, rows); // Agregamos las filas generadas anteriormente al grid
                            $("#GridAseguradora_contRegTotal").text("Reg. Visibles: " + $("#GridAseguradora").jqxGrid('getrows').length)
                        })
                    })(i);
                }
            })
        }, 100);
    })

The Console.logs I wanna obtain:我想获得的 Console.logs:

1-first for loop
obtain 1000 results
(append results)

2-first for loop
obtain 1000 results
(append results)

.....

What I hope is that the client sees that the products are being loaded little by little, not that the remaining 9000 are loaded together我希望的是客户看到产品是一点一点加载的,而不是剩下的9000个一起加载

You are immediately appending the .then() clauses when you run your loop, hence they immediately get resolved.当您运行循环时,您会立即附加.then()子句,因此它们会立即得到解决。 You essentially want to block each loop iteration until the promise resolves and then continue on to the next one and repeat.您基本上想要阻止每个循环迭代,直到 promise 解决,然后继续下一个并重复。

You can do this with async / await too, but here is how you achieve synchronous loop iterations with promises:你也可以使用 async / await 来做到这一点,但这里是你如何使用 Promise 实现同步循环迭代:

let promise = Promise.resolve()

for (let i = 0; i < 10; i++) {
  promise = promise.then(() => {
    fetchData('ArticulosSearch', inputValues).then(res => {
       // your logic here
    })
  })
}

You initialise a new promise with Promise.resolve() and keep appending then() s to it on each loop iterations.您使用Promise.resolve()初始化一个新的 promise 并在每个循环迭代中继续将then()附加到它。 These .then() will execute only when the previous one is resolved.这些.then()仅在前一个解决后才会执行。

This will ensure things are properly scheduled one after another.这将确保事情一个接一个地安排妥当。

Take a look at this snippet, I tried to simulate some async operation that takes variable time to resolve:看看这个片段,我试图模拟一些需要可变时间来解决的异步操作:

 const outputEl = document.getElementById('output') const fetchSomethingFromDBAsyncFake = (idx) => new Promise((resolve, reject) => { const timeout = setTimeout(() => { outputEl.innerHTML += ` <br /> Loaded chunk ${idx} ` resolve() clearTimeout(timeout) }, 500 + Math.random() * 1750) }) let promise = Promise.resolve() for (let i = 0; i < 10; i++) { promise = promise.then(() => fetchSomethingFromDBAsyncFake(i)) }
 <div id="output"></div>

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

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