Tengo una función como el código a continuación, estoy tratando de enviar un archivo a través de XMLHttpRequest al servidor y luego almacenarlo en la base de datos y recuperar la identificación del archivo en la base de datos y crear un objeto de identificaciones. El problema es que la función sale mucho antes de que obtuviera la respuesta del servidor para almacenarla en el objeto, por lo tanto, el objeto no almacena esos valores. Sé que necesito hacer que el XHR sea asincrónico, pero no cambia el resultado, también probé el tiempo de espera o usé una plataforma diferente como Ajax, pero aún así no funcionó.
async function getFileObj() { var FileObject = {} for (let key1 in PObj) { FileObject[key1] = {} for (let key2 in PObj[key1]) { FileObject[key1][key2] = {} for (let key3 in PObj[key1][key2]) { const formData = new FormData(); formData.append('myFile.png', filesObjDB[key1][key2][key3]); var xhr = new XMLHttpRequest(); xhr.open("POST", 'url', true); xhr.onreadystatechange = async function() { if (this.readyState === XMLHttpRequest.DONE && this.status === 200) var id = await xhr.response.text(); FileObject[key1][key2][key3] = parseInt(id) } xhr.responseType = 'blob'; xhr.send(formData); } } } return FileObject; }¡La ayuda seria muy apreciada!
No está esperando la solicitud. Para hacer que el código existente espere el resultado, debe envolver el código obsoleto basado en devolución de llamada en una promesa y esperar eso (y tampoco creo que obtener el texto de respuesta de un XHR funcione como lo mostró, cambié Es ahora):
// This is just to demonstrate what was immediately wrong // with the existing code - it's not the best solution! See below. FileObject[key1][key2][key3] = await new Promise((resolve, reject) => { var xhr = new XMLHttpRequest(); xhr.open("POST", url, true); xhr.onreadystatechange = function() { if (this.readyState === XMLHttpRequest.DONE && this.status === 200) { var id = xhr.responseText; resolve(parseInt(id)); } }; xhr.send(formData); });Tenga en cuenta que aún no hay manejo de errores, si la solicitud falla, todo se bloqueará.
¡Pero en ese momento, en realidad no tiene sentido usar XHR en primer lugar! Es mucho más sencillo usar fetch , que tiene una API prometedora lista para usar :
const response = await fetch(url, { method: 'POST', body: formData }) FileObject[key1][key2][key3] = parseInt(await response.text())