在响应返回之前来自函数的 XMLHttpRequest return

XMLHttpRequest return from a function before response is back

我有如下代码的功能,我试图通过 XMLHttpRequest 将文件发送到服务器,然后将其存储在数据库中,并在数据库中检索文件的 ID 并创建一个 ID 对象。 问题是在我从服务器返回响应以将其存储在对象中之前该函数退出了很多,因此该对象不存储这些值。 我知道我需要使 XHR 异步,但它不会改变结果,我也尝试过超时或使用不同的平台,如 Ajax,但仍然没有用。

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;
}

非常感谢您的帮助!

您没有在等待请求。要使现有代码等待结果,您需要将过时的 callback-based 代码包装在一个承诺中并等待它(而且我认为获取 XHR 的响应文本不会像您展示的那样工作,我现在改了):

// 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);
});

请注意,目前还没有错误处理,如果请求失败,一切都会挂起。

但在这一点上,首先使用 XHR 实际上没有任何意义! 使用 fetch 更直接,它有开箱即用的承诺 API:

const response = await fetch(url, { method: 'POST', body: formData })
FileObject[key1][key2][key3] = parseInt(await response.text())