循环 $http get 中没有作用域?

no scope in loop $http get?

我正在使用 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 总是显示为最后一次交换。 非常感谢您的帮助。谢谢

Yes, your following loop has problem:

      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 通话时在场。

现在要做到这一点,已经使用以下代码创建了一个数组 因为 return 值是一个映射并且很难在下一个递归中使用 功能:

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

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

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();
        }
    );

}

The final updated code given below:

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();
});
});

由于循环中的 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>

试试这个

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);
        });

    });
});