无法使用 2 个有点相似的 XMLHttpRequest 获得相同的结果

Unable to get the same results with 2 pieces of somewhat similar XMLHttpRequest

希望您能够帮助或只是帮助我理解为什么我有 2 个几乎相似的代码块,其中一个不符合我的预期。

我正在尝试进行一些 API 调用,其中我使用从 API 调用中提取的数据填充变量。第一个完全没有问题,但第二个我无法填充变量。 我试过用谷歌搜索这个问题,这似乎是因为 XmlHttprequests 的异步性质。但同样,我不明白为什么一种解决方案有效而另一种无效。

有效的解决方案:

// Get JSON and convert it to an object
var obj;
const Http = new XMLHttpRequest();
const url = "https://type.fit/api/quotes";

Http.open("GET", url);
Http.send();

Http.onreadystatechange = function () {
  if (this.readyState == 4 && this.status == 200) {
    obj = JSON.parse(Http.responseText);
  }
};

在此解决方案中,我能够获取数据并填充变量 obj 并在全局范围内使用它。

link求解:https://codepen.io/Kfriis/pen/QWjGZmx

无效的解决方法:

//function that takes a currency in capital letters and returns 
  var rates;
  var currency = 'gbp';
  const currencyString = currency.toUpperCase();
  const API = "api.frankfurter.app"
  const URL = `https://${API}/latest?amount=1&from=${currencyString}&to=DKK`
  
  const http = new XMLHttpRequest();
  
  http.open("GET", URL);
  http.send();
  
  http.onreadystatechange = function() {
      if (this.readyState == 4 && this.status == 200) {
        rates = JSON.parse(http.responseText);
        
      }
  };
  console.log(rates)

出于某种原因,这确实行不通。我不明白为什么没有填充 rates 变量,因为第一个代码片段的请求基本相同。 我归结为一个想法是因为从 2 API 端点发送的数据可能在某些方面有所不同。因为如果只是因为异步请求,那么两个代码片段都应该 return 未定义。

Link https://codepen.io/Kfriis/pen/VwvpKmd

我确实希望有人能够对此有所启发。 我一定是在第二个片段中做错了什么,因为我可以 console.log() 从 onreadystatechange 内部而不是外部。这让我很长一段时间都认为这是一个范围界定问题。

您的代码确实有效。但是,您在 http.onreadystatechange 函数之外记录 console.log(rates),这意味着您在获得响应之前记录了速率。如果更改代码块

 http.onreadystatechange = function() {
      if (this.readyState == 4 && this.status == 200) {
        rates = JSON.parse(http.responseText);

      }
  };
  console.log(rates)

 http.onreadystatechange = function() {
      if (this.readyState == 4 && this.status == 200) {
        rates = JSON.parse(http.responseText);
        console.log(rates)
      }
  };

应该可以。

如果您想将代码添加到函数,这里有一个有效的示例代码。

// Function that takes a currency in capital letters and returns 
function getCurrencyRates(currency, cb) {
  const currencyString = currency.toUpperCase();
  const API = "api.frankfurter.app"
  const URL = `https://${API}/latest?amount=1&from=${currencyString}&to=DKK`

  const http = new XMLHttpRequest();

  http.open("GET", URL);
  http.send();

  http.onreadystatechange = function() {
        if (this.readyState == 4 && this.status == 200) {
            cb(JSON.parse(http.responseText));        
        }
  };
}

// Call the function and pass "gbp" as currency.
// Rates will be logged in response.
getCurrencyRates('gbp', function(response) {
    console.log(response);
});