【问题标题】:Using jquery.when and done to pass a value from one ajax call to another使用 jquery.when 和 done 将值从一个 ajax 调用传递给另一个
【发布时间】:2016-08-17 15:31:12
【问题描述】:

我正在尝试在第二个 ajax 调用中使用第一个 ajax 调用的值。我正在使用下面的代码结构。出于某种原因,第二次调用为userLocation variable 返回undefined。如何重构我的代码,以便可以在第二个 ajax 调用的 url 中使用第一个 ajax 调用的 userLocation 值?

var userLocation;

function getUserLocation() {
  $.ajax({
    url: 'https://www.example.com/location.json',
    success: function(response) {
      userLocation = response.coordinates;
    }
  });
}

function getCurrentWeather() {
  $.ajax({
    url: 'https://www.example.com/weather' + userLocation +  '.json',
    success: function(response) {
      console.log(response);
    }
  });
}


$(document).ready(function() {
  $.when(
    getUserLocation()
  ).done(
    getCurrentWeather()
  )
});

更新 1: 感谢下面提供的答案,我已经能够重构我的代码。现在从第一个 ajax 调用收到的值可以在第二个 ajax 调用中使用。这是更新的代码:

var userLocation;

function getUserLocation() {
  return $.ajax('https://www.example.com/location.json')
  .then(function(response) {
    return JSON.parse(response);
  }).then(function(json) {
    // data from the location.json file is available here
    userLocation = json.coordinates;
  })
}

function getCurrentWeather() {
  return $.ajax('https://www.example.com/weather' + userLocation +  '.json');
}


getUserLocation().then(getCurrentWeather).then(function(data) {
  // data from the weather(userLocation).json file is available here
});

【问题讨论】:

    标签: javascript jquery ajax asynchronous promise


    【解决方案1】:

    jQuery 的 ajax 返回 Promise,你可以使用它:

    function getUserLocation() {
      return $.ajax('https://www.example.com/location.json'); // note the `return`
    }
    
    function getCurrentWeather(userLocation) {
      return $.ajax('https://www.example.com/weather' + userLocation +  '.json');
    }
    
    getUserLocation().then(getCurrentWeather).then(function(data) {
       // location data here
    });
    

    或者,更详细的

    getUserLocation().then(function (user) { 
        return getCurrentWeather(user); 
    }).then(function(data) {
       // location data here
    });
    

    更好的解决方案是进行一次调用而不是两次调用,因为进行大量 AJAX 调用会降低您的应用程序的速度,尤其是在带宽有限的移动设备上。


    这是一种基于回调的方法,它可能不如基于承诺的方法(例如错误处理)——但我觉得我们应该为了完整性而展示它。您可以阅读通用解决方案in this thread

    function getUserLocation(callback) {
      $.ajax('https://www.example.com/location.json', callback)
    }
    
    function getCurrentWeather(userLocation, callback) {
      $.ajax('https://www.example.com/weather' + userLocation +  '.json', callback);
    }
    
    getUserLocation(function(user) {
       getCurrentWeather(user, function(weather) {
           console.log("Got weather", weather); 
       });
    });
    

    【讨论】:

    • 我也不知道为什么这段代码在 $(document).ready 里面——这只是无缘无故地减慢速度。
    • 我已经添加了一个更新的代码,我已经按照你的解决方案,并且我已经删除了$(document).ready。我稍微修改了方法,例如我没有将参数传递给getCurrentWeather() 函数。它达到了预期的结果,尽管我不确定它是否遵循良好的做法。
    • 您正在使用可变的全局状态,这很糟糕 - 它会导致不必要的错误,并且远非一个好的做法。这种代码的问题是调试它而不是编写它。
    • 我只是无法使用严格的承诺解决方案使其工作。我应该在哪个函数中将从location.json 文件获得的坐标分配给userLocation 变量,以便它可以传递给getCurrentWeather()?或者也许我不应该使用 userLocation 作为变量?另外我在哪里可以处理天气数据?这是我的主要目标,但是在您的解决方案中,您评论说位置数据(不是天气数据)可以在代码的最后部分进行处理。这让我很困惑,因为我希望我可以在这个阶段开始处理天气数据。
    • 执行getUserLocation().then(getCurrentWeather).then(function(data) { /*location data*/ }); 确实是getUserLocation().then(function(location) { return getCurrentWeather(location); }).then(function(data) { ... - 承诺链 - 数据通过它们之间的第一个参数传输 - 这就是实际情况。
    【解决方案2】:

    由于某种原因,第二次调用为 userLocation 变量返回 undefined

    这是因为您没有从 ajax 调用返回承诺,请参阅 Benjamin 的回答以了解如何执行此操作。

    如何重构我的代码,以便在第二个 ajax 调用的 url 中使用第一个 ajax 调用的 userLocation 值?

    重构您的代码以在第一次调用中嵌套对另一个函数的调用:

    var userLocation;
    
    function getUserLocation() {
      $.ajax({
        url: 'https://www.example.com/location.json',
        success: function(response) {
          // set the user location
          userLocation = response.coordinates;
          // make call to second function passing in userLocation
          getCurrentWeather(userLocation);
        }
      });
    }
    
    function getCurrentWeather(userLocation) {
      $.ajax({
        url: 'https://www.example.com/weather' + userLocation +  '.json',
        success: function(response) {
          console.log(response);
        }
      });
    }
    
    $(document).ready(function() {
        getUserLocation()
    });
    

    如果您没有在其他任何地方使用变量 userLocation,请节省一些代码:

    function getUserLocation() {
      $.ajax({
        url: 'https://www.example.com/location.json',
        success: function(response) {
          // make call to second function passing in coordinates from response
          getCurrentWeather(response.coordinates);
        }
      });
    }
    
    function getCurrentWeather(userLocation) {
      $.ajax({
        url: 'https://www.example.com/weather' + userLocation +  '.json',
        success: function(response) {
          console.log(response);
        }
      });
    }
    
    $(document).ready(function() {
        getUserLocation()
    });
    

    【讨论】:

    • 我的想法类似,但我试图将 'getCurrentWeather()' 函数与 'getUserLocation()' 函数分离,以便代码更优雅。这可能吗?
    • 是的,请参阅@Benjamin 的回答
    【解决方案3】:

    你应该这样做:

    function getUserLocation() {
      return $.ajax({
        url: 'https://www.example.com/location.json',
        success: function(response) {
          userLocation = response.coordinates;
        }
      });
    }
    
    function getCurrentWeather(userLocation) {
      return $.ajax({
        url: 'https://www.example.com/weather' + userLocation +  '.json',
        success: function(response) {
          console.log(response);
        }
      });
    }
    
    
    $(document).ready(function() {
      $.when(
        getUserLocation()
      ).done(
        getCurrentWeather
      )
    });
    
    1. 从 getUserLocation 返回 $.ajax(...)
    2. getCurrentWeather 是作为函数传递的,你不应该在 done 中调用它,它会在 getUserLocation 完成后调用 async。

    编辑#2:将getCurrentWeather() 放入.done(...) 的错误在于该函数将立即调用。但是,.done(...) 应该传入一个函数,该函数将在解决 $.when() 承诺后调用。

    正如Benjamin Gruenbaum所说,最好使用.done(...)然后.then(...)

    【讨论】:

    • 您的$.when 实际上并没有做任何事情,您的done 应该是then
    • 同意。我认为@Piotr Berebecki 应该跟随你的answer。我最初只是试图对他的原始代码进行细微的更改,以指出他做错了什么。
    【解决方案4】:

    可以是这样的:

    var userLocation;
    
    function getUserLocation() {
      $.ajax({
        url: 'https://www.example.com/location.json',
        success: function(response) {
          userLocation = response.coordinates;
        }
      }).done(function() {
           getCurrentWeather()
      });
    }
    
    function getCurrentWeather() {
      $.ajax({
        url: 'https://www.example.com/weather' + userLocation +  '.json',
        success: function(response) {
          console.log(response);
        }
      });
    }
    

    【讨论】:

    • 我的想法类似,但我试图将 'getCurrentWeather()' 函数与 'getUserLocation()' 函数分离,以便代码更优雅。这可能吗?
    • @PiotrBerebecki 是的,通过回调或承诺:我会在我的回答中修改它。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-19
    • 1970-01-01
    • 2018-10-02
    • 1970-01-01
    • 2018-02-05
    • 1970-01-01
    相关资源
    最近更新 更多