Javascript /起重或承诺范围/延期吗?

时间:2021-10-10 01:20:41

I am trying to make an external AJAX call to an API within a Jquery each loop.

我正在尝试在Jquery每个循环中对API进行外部AJAX调用。

Here is the code I have so far.

这是我到目前为止的代码。

getStylesInfo(tmpMake, tmpModel, tmpModelYear, tmpSubmodel).done(function(data){
    var holder = [];

    $.each(styles, function(index, value) {
        var tempValue = value;
        var temp = getNavigationInfo(value.id);

        $.when(temp).done(function(){
            if(arguments[0].equipmentCount == 1){
                holder.push(tempValue);
                console.log(holder);
            }
        });
    });
});

console.log(holder);

function getStylesInfo(make, model, year, submodel){
    return $.ajax({
    type: "GET",
    url: apiUrlBase + make + '/' + model + '/' + year + '/' + 'styles?  fmt=json&' + 'submodel=' + submodel + '&api_key=' + edmundsApiKey + '&view=full',
   dataType: "jsonp"
});   


function getNavigationInfo(styleId){
    return $.ajax({
    type: "GET", 
    url: apiUrlBase + 'styles/' + styleId + '/equipment?availability=standard&name=NAVIGATION_SYSTEM&fmt=json&api_key=' + edmundsApiKey,
    dataType: "jsonp"
});   

The getStylesInfo() returns something similar to this. An array of objects with info about a car model.

getStylesInfo()返回类似的内容。一组具有汽车模型信息的对象。

var sampleReturnedData = [{'drivenWheels': 'front wheel drive', 'id': 234321}, {'drivenWheels': 'front wheel drive', 'id': 994301}, {'drivenWheels': 'rear wheel drive', 'id': 032021}, {'drivenWheels': 'all wheel drive', 'id': 184555}];  

I am trying to loop through the sampleReturnedData and use each id as a parameter in a different AJAX call with the getNavigationInfo() function.

我尝试遍历sampleReturnedData,并使用每个id作为getNavigationInfo()函数在不同的AJAX调用中的参数。

I want to loop through the results and make a check. If it is true then I want to push the entire object to the holder array.

我想对结果进行循环检查。如果为真,那么我想将整个对象推到holder数组中。

The problem is the console.log(holder) outside the function returns an empty array. The console.log(holder) within the if statement works properly.

问题是函数外的console.log(holder)返回一个空数组。if语句中的console.log(holder)工作正常。

I am not sure if this is a scope/hoisting issue or a problem with the way I am using deferreds?

我不确定这是一个范围/提升的问题还是我使用延期的方式的问题?

I have read this question and many like it. They suggest to use either

我读过这个问题,很多人都喜欢。他们也建议使用。

async:false

Or to rewrite the code better. I have tried and used console debugger numerous times. I don't want to set it to false. I'm just unsure what exactly is going on.

或者更好地重写代码。我试过无数次使用控制台调试器。我不想把它设为false。我只是不确定到底发生了什么。

I've also read up on hoisting via this article.

我也读过这篇文章。

I believe it has to do with deferreds but I don't have enough JS knowledge to figure it out.

我认为这与延期有关,但我没有足够的JS知识来解决这个问题。

Thanks!

谢谢!

1 个解决方案

#1


3  

I am not sure if this is a scope/hoisting issue or a problem with the way I am using deferreds?

我不确定这是一个范围/提升的问题还是我使用延期的方式的问题?

In fact, it is both:

事实上,这两者都是:

  • holder is declared only within the callback function (as a local variable), so it's undefined outside the function.
  • holder仅在回调函数中声明(作为局部变量),因此在函数之外没有定义。
  • And the console.log is executed before the asynchronous callback function does fill the array with values, so even if holder was in scope it would still have been empty. See also Why is my variable unaltered after I modify it inside of a function? - Asynchronous code reference
  • 和控制台。在异步回调函数用值填充数组之前执行日志,因此即使holder在作用域中,它仍然是空的。还可以看到为什么我的变量在函数中修改后没有被修改?——异步代码参考

So what you should do is indeed to rewrite your code to use promises properly :-)

因此,你应该做的是重写你的代码以正确地使用承诺:-)

getStylesInfo(tmpMake, tmpModel, tmpModelYear, tmpSubmodel).then(function(data) {
    var holder = [];
    var promises = $.map(data.styles, function(value, index) {
        return getNavigationInfo(value.id).then(function(v){
            if (v.equipmentCount == 1)
                holder.push(value);
        });
    });
    return $.when.apply($, promises).then(function() {
        return holder;
    }); // a promise for the `holder` array when all navigation requests are done
}).then(function(holder) {
    console.log(holder); // use the array here, in an async callback
});

#1


3  

I am not sure if this is a scope/hoisting issue or a problem with the way I am using deferreds?

我不确定这是一个范围/提升的问题还是我使用延期的方式的问题?

In fact, it is both:

事实上,这两者都是:

  • holder is declared only within the callback function (as a local variable), so it's undefined outside the function.
  • holder仅在回调函数中声明(作为局部变量),因此在函数之外没有定义。
  • And the console.log is executed before the asynchronous callback function does fill the array with values, so even if holder was in scope it would still have been empty. See also Why is my variable unaltered after I modify it inside of a function? - Asynchronous code reference
  • 和控制台。在异步回调函数用值填充数组之前执行日志,因此即使holder在作用域中,它仍然是空的。还可以看到为什么我的变量在函数中修改后没有被修改?——异步代码参考

So what you should do is indeed to rewrite your code to use promises properly :-)

因此,你应该做的是重写你的代码以正确地使用承诺:-)

getStylesInfo(tmpMake, tmpModel, tmpModelYear, tmpSubmodel).then(function(data) {
    var holder = [];
    var promises = $.map(data.styles, function(value, index) {
        return getNavigationInfo(value.id).then(function(v){
            if (v.equipmentCount == 1)
                holder.push(value);
        });
    });
    return $.when.apply($, promises).then(function() {
        return holder;
    }); // a promise for the `holder` array when all navigation requests are done
}).then(function(holder) {
    console.log(holder); // use the array here, in an async callback
});