如何避免javascipt中的XMLhttpReuest回调地狱

问题描述

我需要使用来自两个不同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

解决方法

所以您要一个接一个地做?为什么不在第一个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);

}
}