【问题标题】:how to avoid XMLHttpRequest callback hell in javascript如何避免 JavaScript 中的 XMLHttpRequest 回调地狱
【发布时间】:2021-01-31 08:39:36
【问题描述】:

我需要使用来自两个不同 API 调用的响应来构建我的模型,并且我不想进行嵌套回调。这个想法是进行两个单独的调用,然后等待直到两个调用都响应然后调用模型函数

    let data = null
    let forecast = null
    const dataRequest = new XMLHttpRequest()
    dataRequest.responseType = 'json';
    dataRequest.open('GET', urlData)
    dataRequest.send()
    dataRequest.onload = () => data = dataRequest.response


    const forecastRequest = new XMLHttpRequest()
    forecastRequest.responseType = 'json';
    forecastRequest.open('GET', urlForecast)
    forecastRequest.send()
    forecastRequest.onload = () => forecast = forecastRequest.response
  

setTimeout(
        function () {
          const theModel = model(data, forecast) // data,forecast are null
        }, 0); // this will work if I set the waiting time to 100 instead of 0

问题在于执行顺序与预期不符。 在文档中,明确说明当使用 setTimeout 方法或任何其他异步调用时,该函数将被插入事件队列中。因此,在我的应用程序中,第一个 onload 方法将首先插入到事件队列中,然后将插入第二个 onload,最后,setTimeout 将是最后一个插入的方法(所以我希望它是最后一个也被执行)。但是执行顺序显示了一些不同:setTimeout 函数将首先执行,即使 setTimeout 是队列中的最后一个并且它应该是最后一个要执行的函数 https://developer.mozilla.org/en-US/docs/Web/JavaScript/EventLoop

【问题讨论】:

  • 尝试使用带有“await”的 fetch API。它将类似于: const resp1 = await fetch(urlData);常量数据 = 等待 resp1.json(); const resp2 = await fetch(urlForecast);常量预测 = 等待 resp2.json();

标签: javascript asynchronous callback xmlhttprequest settimeout


【解决方案1】:

所以你想一个接一个地做?为什么不在第一次 onload 事件后发出第二次请求,在第二次 onload 后发出模型?

let data = null
let forecast = null
let theModel = null

const dataRequest = new XMLHttpRequest()

dataRequest.responseType = 'json';
dataRequest.open('GET', urlData)
dataRequest.send()
dataRequest.onload = () => {

        data = dataRequest.response;

        const forecastRequest = new XMLHttpRequest()
        forecastRequest.responseType = 'json';
        forecastRequest.open('GET', urlForecast)
        forecastRequest.send()
        forecastRequest.onload = () => {

                forecast = forecastRequest.response;

                theModel = model(data, forecast);

}
}

【讨论】:

  • 谢谢查理,但这正是我想要避免的,我不想进行嵌套回调。原因是我不希望第二个电话依赖于第一个电话。如果第一次调用失败,您的示例中会发生什么? ,您将永远没有机会在第二次调用时调用 onload。
  • 是的,但是当您将 setTimeout 设置为 0 并且不等待 xhr 结果时,您的 setTimeout 将首先准备好
  • 如果其中一个 xhr 调用失败,您可以使用 xhr.onerror = function() { // 仅在根本无法发出请求时触发 };
  • 你这里其实有点意思,但是我还是没看懂执行顺序,是什么我从事件队列中没有正确理解? setTimeout(func(),0) 应该总是最后一个执行,即使我将它设置为 0。这就是超时的点,否则我为什么每次人们演示异步编程时都用它来模拟异步行为在 JavaScript 中
  • 超时的执行开始时间是最后一个是的,但是当你设置它为0时它在XML请求之前就准备好了。因为XML请求比超时需要更多的时间来完成。
猜你喜欢
  • 2017-05-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-08-18
  • 1970-01-01
  • 1970-01-01
  • 2018-09-11
  • 2019-02-24
相关资源
最近更新 更多