【问题标题】:no scope in loop $http get?循环 $http get 中没有范围?
【发布时间】:2018-08-12 09:16:46
【问题描述】:

我正在使用 2 个 API 点。 第一个是获取所有交易所,第二个是从第一点开始打印每个交易所的 BTC 价格。然后我想将两个调用合并到 1 个对象

var app = angular.module("App", []);   
app.controller("Ctrl", function ($scope, $http) {
    var rand = [];
    $http({
        method: "GET",
        url: "https://min-api.cryptocompare.com/data/all/exchanges" 
    }).then(function success(response) {
        var datas = response.data;
        for (var prop in datas) {

            $http.get("https://min-api.cryptocompare.com/data/pricemulti?fsyms=BTC&tsyms=USD&e=" + prop)
            .then(function success(responsePrice) {
            rand.push({'exchange' : prop, 'price' : responsePrice.data});
            })
        }

    });
    console.log(rand);
});

如果我不将它们放在一起,API 点就可以正常工作。在我的 http get 中有一个循环是不是很糟糕?似乎我在成功函数之后没有范围,所以 prop 总是显示为最后一个交换。 将非常感谢您的帮助。谢谢

【问题讨论】:

    标签: angularjs asynchronous scope http-get


    【解决方案1】:

    由于循环中的async 任务,您的prop 范围将始终丢失。要保留prop 的范围,您必须使用let 而不是var,因为var 具有function 范围,而let 具有block 范围。所以你修改后的代码将是

    var app = angular.module("App", []);   
    app.controller("Ctrl", function ($scope, $http) {
        var rand = [];
        $http({
            method: "GET",
            url: "https://min-api.cryptocompare.com/data/all/exchanges" 
        }).then(function success(response) {
            var datas = response.data;
            for (let prop in datas) {
    
                $http.get("https://min-api.cryptocompare.com/data/pricemulti?fsyms=BTC&tsyms=USD&e=" + prop)
                .then(function success(responsePrice) {
                rand.push({'exchange' : prop, 'price' : responsePrice.data});
                })
            }
    
        });
        console.log(rand);
    });
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>

    【讨论】:

      【解决方案2】:

      是的,您的以下循环有问题:

            for (var prop in datas) {
      
                  $http.get("https://min-api.cryptocompare.com/data/pricemulti?fsyms=BTC&tsyms=USD&e=" + prop)
                  .then(function success(responsePrice) {
                  rand.push({'exchange' : prop, 'price' : responsePrice.data});
                  })
              }
      

      for (var prop in datas) { 行执行其所有迭代并 指向完成$http.get 请求之前的最后一个元素作为它的 异步请求。

      所以,要做到这一点,需要一些机制来保证数据的合法性 在$http.get 通话时在场。

      现在要执行此操作,已使用以下代码创建了一个数组 因为返回值是一个映射,并且很难在下一个递归中使用 功能:

      datas = response.data;
      console.log(datas);
      for (var prop in datas) {
         propArray.push(prop);
      }
      

      以下递归函数可确保在每个 $http.get 完成后更新您使用的 prop 项目的值:

      var dataAcquireLoop = function () {
          dataIndex++;
          if(dataIndex >= propArray.length) {
              console.log(rand);
              return;
          }
          console.log(propArray[dataIndex]);
          $http.get("https://min-api.cryptocompare.com/data/pricemulti?fsyms=BTC&tsyms=USD&e=" + propArray[dataIndex])
          .then(
              function success(responsePrice) {
                  rand.push({'exchange' : propArray[dataIndex], 'price' : responsePrice.data});
                  dataAcquireLoop();
              },
              function(error) {
                  dataAcquireLoop();
              }
          );
      
      }
      

      下面给出的最终更新代码:

      app.controller("Ctrl", function ($scope, $http) {
      var rand = [];
      var datas = [];
      var dataIndex = -1;
      var propArray = [];
      var dataAcquireLoop = function () {
          dataIndex++;
          if(dataIndex >= propArray.length) {
              console.log(rand);
              return;
          }
          console.log(propArray[dataIndex]);
          $http.get("https://min-api.cryptocompare.com/data/pricemulti?fsyms=BTC&tsyms=USD&e=" + propArray[dataIndex])
          .then(
              function success(responsePrice) {
                  rand.push({'exchange' : propArray[dataIndex], 'price' : responsePrice.data});
                  dataAcquireLoop();
              },
              function(error) {
                  dataAcquireLoop();
              }
          );
      
      }
      
      $http({
          method: "GET",
          url: "https://min-api.cryptocompare.com/data/all/exchanges" 
      }).then(function success(response) {
          datas = response.data;
          console.log(datas);
          for (var prop in datas) {
             propArray.push(prop);
          }
          dataAcquireLoop();
      });
      });
      

      【讨论】:

        【解决方案3】:

        试试这个

        var app = angular.module("App", []);
        app.controller("Ctrl", function ($scope, $http) {
            var rand = [];
            $http({
                method: "GET",
                url: "https://min-api.cryptocompare.com/data/all/exchanges"
            }).then(function success(response) {
                var datas = response.data;
                var keys = Object.keys(datas);
                var promises = keys.map(prop =>
                    $http.get("https://min-api.cryptocompare.com/data/pricemulti?fsyms=BTC&tsyms=USD&e=" + prop));
        
                Promise.all(promises).then((response) => {
                    rand = response.map((responsePrice, index) => {
                        return {
                            'exchange': keys[index],
                            'price': responsePrice.data
                        };
                    });
                    console.log(rand);
                }).catch((err) => {
                    console.log(err);
                });
        
            });
        });
        

        【讨论】:

        • 不幸的是交换是'未定义'
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-07-21
        • 1970-01-01
        • 1970-01-01
        • 2013-08-17
        • 2018-12-11
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多