Este es un blog escrito por ChatGPT: vue3&js pit: inicie una solicitud de red en un bucle y el resultado devuelto son solo los datos de la última solicitud de red


Durante el proceso de desarrollo, quise registrar un error que encontré, después de terminar de escribir el blog, tuve un capricho y le pedí a ChatGPT que me ayudara a escribir un blog con el mismo contenido.

inserte la descripción de la imagen aquí

lo escribí yo mismo

Escenas

Necesito iniciar una solicitud de red en un bucle y almacenar los datos devueltos por la solicitud de red en la base de datos frontal RxDB en cada bucle. Yo uso el método forEach para lograr:

this.befDataview.forEach(async (i)=>{
    
    
	const dbDataview=await api.insertDataview(this.afterDatasetId,aftDataview)
	const result=await this.$rxdb dataview.insert(dbDataview)
})

El código anterior es un bucle de 3 tiempos, y cada bucle inicia una solicitud de red al backend y luego inserta los datos solicitados dbDataview en rxdb.

bicho

Después de ejecutar el código anterior, rxdb informa un error: el documento con la misma clave principal (id) no se puede insertar repetidamente. Después de la depuración, se encuentra que en los 3 bucles, los datos de la última solicitud de red se insertarán en rxdb cada vez, es decir, el resultado devuelto después de 3 bucles solo contiene los datos de la última solicitud de red.

resolver

Revisé las solicitudes en la red y descubrí que los datos devueltos por el backend son correctos cada vez, por lo que el problema solo puede estar en el frontend. Siento vagamente que hay un problema con la parte asíncrona, pero no sé dónde está y cómo resolverlo. Pregunté a ChatGPT y finalmente encontré el problema.

Esto se debe a que forEachel método no esperará asyncel valor de retorno de la función, por lo que continuará ejecutando el siguiente ciclo sin esperar a que se complete la operación asincrónica actual. Por lo tanto, el método en mi código rxdb.insert()solo insertará los datos devueltos por la última solicitud después de que se completen todas las solicitudes de red.

Se debe usar for...ofun bucle o método Promise.all()para resolver este problema. for...ofMientras el bucle espera a que se complete cada awaitexpresión antes de pasar a la siguiente iteración, Promise.all()puede esperar a que se completen todas las operaciones asincrónicas antes de pasar al siguiente paso.

Aquí hay for...ofun código de muestra usando un bucle:

for(const i of this.befDataview){
    
    
  const dbDataview = await api.insertDataview(this.afterDatasetId, aftDataview);
  const result = await this.$rxdb.dataview.insert(dbDataview);
}

Aquí hay Promise.all()un código de muestra para saber cómo usarlo:

await Promise.all(this.befDataview.map(async i => {
    
    
  const dbDataview = await api.insertDataview(this.afterDatasetId, aftDataview);
  const result = await this.$rxdb.dataview.insert(dbDataview);
}));

en conclusión

En mi código, las solicitudes de red y rxdblas operaciones insertse escriben en el mismo bucle, pero su orden de ejecución no es el que esperaba.

Específicamente, forEachel ciclo inicia múltiples operaciones asincrónicas en el cuerpo del ciclo, es decir, múltiples solicitudes de red y múltiples rxdboperaciones insert. Dado que forEachel método no espera asyncel valor de retorno de la función, continúa con la siguiente iteración inmediatamente sin esperar a que se complete la operación asíncrona actual. Esto significa que si uso awaituna expresión en el cuerpo del bucle, solo esperará a que se complete la operación asincrónica actual antes de continuar con el siguiente paso, en lugar de esperar a que se completen todas las operaciones asincrónicas antes de continuar con la siguiente iteración.

Por lo tanto, en mi código, los resultados de las solicitudes de red y el orden de ejecución rxdbde insertlas operaciones son indeterminados, según el tiempo de respuesta y el tiempo de procesamiento de cada operación asíncrona. Normalmente, los resultados de la última solicitud de red se insertan en último lugar en rxdb.

Para garantizar que cada operación asíncrona se pueda ejecutar en el orden que espero y que no se vea afectada por otras operaciones, debo usar un for...ofciclo o Promise.all()método para garantizar que cada operación asíncrona se pueda ejecutar en secuencia y esperar a que se ejecuten todas las operaciones asíncronas. operaciones para completar antes Continúe con el siguiente paso.

El anterior es el resumen de mi propio blog. Después de que terminé de escribirlo, tuve un capricho, ¿por qué no simplemente pedirle a ChatGPT que me ayude a escribir un blog? Así que hay el siguiente contenido.

ChatGPT me ayudó a escribir

Tema: Cómo evitar errores causados ​​por iniciar solicitudes de red en bucles en Vue3

En Vue3, a menudo necesitamos iniciar solicitudes de red en un bucle para procesar datos. Sin embargo, en tales escenarios, si el código no se escribe con cuidado, puede causar algunos problemas impredecibles. Este blog presentará cómo evitar los problemas causados ​​por el inicio de solicitudes de red en un bucle y brindará algunos consejos prácticos para ayudarlo a escribir un código más sólido.

Descripción del problema

Recientemente encontré un problema: necesito usar forEachun bucle en Vue3 para procesar una recopilación de datos y, al mismo tiempo, iniciar una solicitud de red en el cuerpo del bucle e insertar el resultado de la solicitud en él rxdb. Sin embargo, descubrí que al insertar datos en rxdb, los datos insertados cada vez son el resultado devuelto por la última solicitud de red. Esto me impide manejar mis datos correctamente y conduce a algunos errores impredecibles.

Solución

Después de algunas investigaciones e intentos, descubrí que la causa raíz del problema era que estaba forEachusando async/awaitexpresiones dentro del bucle. Dado que forEachel método no espera asyncel valor de retorno de la función, continúa con la siguiente iteración inmediatamente sin esperar a que se complete la operación asíncrona actual. Esto significa que si usa awaituna expresión en el cuerpo del ciclo, solo esperará a que se complete la operación asincrónica actual antes de continuar con el siguiente paso, en lugar de esperar a que se completen todas las operaciones asincrónicas antes de continuar con la siguiente iteración.

Para evitar este problema, podemos usar for...ofbucles o Promise.all()métodos para garantizar que cada operación asincrónica se pueda ejecutar en secuencia y esperar a que se completen todas las operaciones asincrónicas antes de continuar con el siguiente paso. Por ejemplo, el siguiente es un código de muestra que utiliza for...ofun bucle para procesar una recopilación de datos, inicia una solicitud de red e inserta el resultado de la solicitud en el cuerpo del bucle :rxdb

for(const i of this.befDataview){
    
    
  const dbDataview = await api.insertDataview(this.afterDatasetId, aftDataview);
  const result = await this.$rxdb.dataview.insert(dbDataview);
}

En este ejemplo, usamos for...ofun ciclo para procesar cada elemento en la recopilación de datos por turno. En el cuerpo del ciclo, primero iniciamos una solicitud de red para obtener datos y luego insertamos los datos obtenidos en rxdb. Dado que usamos awaituna expresión, esperará a que se complete la operación asincrónica actual antes de continuar con la siguiente iteración, lo que garantiza que cada operación asincrónica se pueda ejecutar en secuencia y espera a que se completen todas las operaciones asincrónicas antes de continuar con el paso siguiente. Con este método, podemos evitar problemas causados ​​por iniciar solicitudes de red en un bucle y garantizar la corrección y solidez del código.

En lugar de usar for...ofbucles, también podemos usar Promise.all()métodos para manejar operaciones asincrónicas. Promise.all()El método toma una Promisematriz de objetos y devuelve un nuevo Promiseobjeto. Este nuevo Promiseobjeto se resolverá Promisecuando todos los objetos se completen correctamente y los valores resueltos se almacenarán en una matriz. Por ejemplo, aquí hay un código de muestra que usa Promise.all()métodos para manejar operaciones asincrónicas:

await Promise.all(this.befDataview.map(async i => {
    
    
  const dbDataview = await api.insertDataview(this.afterDatasetId, aftDataview);
  const result = await this.$rxdb.dataview.insert(dbDataview);
}));

En este ejemplo, primero usamos map()métodos para asignar cada elemento de la recopilación de datos a un Promiseobjeto y Promisealmacenar estos objetos en una matriz. Luego usamos Promise.all()métodos para esperar a que todos Promiselos objetos se completen con éxito, almacenando sus valores de retorno en una matriz. De esta forma, podemos ejecutar operaciones asincrónicas en paralelo y solo continuar con el siguiente paso después de completar todas las operaciones, lo que ayuda a mejorar el rendimiento y la eficiencia del código.

Resumir

En Vue3, realizar solicitudes de red en un bucle puede causar algunos problemas impredecibles, como datos incorrectos o una operación de código anormal. Para evitar este problema, podemos usar for...ofbucles o Promise.all()métodos para garantizar que cada operación asincrónica se pueda ejecutar en secuencia y esperar a que se completen todas las operaciones asincrónicas antes de continuar con el siguiente paso. Esto mejora la corrección y solidez del código, al mismo tiempo que ayuda a mejorar el rendimiento y la eficiencia del código.

Este artículo está aquí. Tengo que decir que la capacidad de expresión del lenguaje de ChatGPT es demasiado fuerte, y la descripción del problema es clara y precisa. En contraste, lo que escribí solo puede llamarse notas, no blogs.

Supongo que te gusta

Origin blog.csdn.net/weixin_45605541/article/details/130016646
Recomendado
Clasificación