多个ajax调用async Action会破坏代码

时间:2016-09-13 21:15:34

标签: c# jquery ajax asp.net-mvc asynchronous

我在.Net Core Framework中编写Web应用程序,并且前端的某些元素使用Ajax调用返回特定数据的API。

如果我在一个需要1个API调用的页面上,它工作正常,但是当我进入一个调用多个调用的页面时,调试(好吧,在代码中逐行)调试器在代码中上下跳动变得很糟糕,最后结果都会以错误结束。

如果一个网站拨打更多电话,我很少能得到结果,有时它会发生,但可能性是...... 1/50,这是不可接受的。

奇怪的是,在我访问这样的页面然后返回到进行1次呼叫的页面时,即使该1次呼叫以错误结束。

我不确定我需要在这里包含什么作为代码,所以我将添加jquery和动作。

在此处输入任何代码之前,我想解释一下我的问题.. 我想知道究竟是什么造成了这种情况,为什么ajax调用导致Action的并行执行?我怎么能强制ajax调用逐个运行或者做任何其他事情来解决这个问题。我相信一些观点最多应该拨打30,40个电话,如果有2个电话会引起这样的问题,那么这里显然存在一个问题,但不幸的是我还没有足够的技能来查看和修复它。 / p>

非常感谢任何帮助。

jquery(我已经删除了一些代码,因为它们并不相关。它只是一些类更改):

$(window).ready(function () {

$('.price').each(function (i, e) {
    var id = $(e).data('skinid');
    var exterior = $(e).data('exterior');
    var type = $(e).data('type');

    $.ajax({
        type: "GET",
        url: "/Skin/GetPrice",
        data: { Id: id, Exterior : exterior, Type : type },
        cache: false,
        dataType: "json",

    }).complete(function (data) {
        var price = data.responseJSON.price;
        if (data.responseJSON.querySuccessful)
        {
            if (data.responseJSON.listingExists)
            {
                //do stuff here
            }
            else
            {
                //other stuff here
            }
        }
        else
        {
                //print error..
        }
    });
});

});

行动很长,所以我也将其缩短:

[HttpGet]
public async Task<ActionResult> GetPrice(int Id = 0, string Exterior = null, string Type = null)
{
    PriceViewModel model = null;
    if (_context.Skins.Any(x => x.Id == Id))
    {
        if (Type == "Skin")
        {
            Skin Query = _context.Skins.Where(x => x.Id == Id).Include(x => x.Weapon).Include(x => x.Quality).Select(x => x).Single();

            using (var client = new HttpClient())
            {
                try
                {
                    string uri = "/market/priceoverview/?currency=3&appid=730&market_hash_name=" + Query.Weapon.Name.Replace(" ", "%20") + "%20|%20" + Query.Name.Replace(" ", "%20") + "%20(" + Exterior.Replace(" ", "%20") + ")";

                    client.BaseAddress = new Uri("http://steamcommunity.com");
                    var response = await client.GetAsync(uri);
                    response.EnsureSuccessStatusCode(); // Throw in not success

                    var stringResponse = await response.Content.ReadAsStringAsync();
                    JObject data = JObject.Parse(stringResponse);

                    if (data["success"].Value<bool>())
                    {
                        if (data["lowest_price"] != null)
                        {
                            // return good model
                        }
                        //return no result model
                    }
                }
                catch
                {
                    // return error
                }
            }
        }

        if (Type == "Skin-List")
        {
            Skin Query = _context.Skins.Where(x => x.Id == Id).Include(x => x.Weapon).Include(x => x.Quality).Select(x => x).Single();

            Dictionary<Exterior, PriceViewModel> PossibleExteriors = new Dictionary<Exterior, PriceViewModel>();

            bool possible = false;
            foreach (Exterior e in _context.Exteriors)
            {
                if (e.Name == Query.BestExterior)
                    possible = true;

                if (possible)
                    PossibleExteriors.Add(e, null);

                if (e.Name == Query.WorstExterior)
                    possible = false;
            }
            List<Exterior> exteriors = PossibleExteriors.Keys.ToList();
            foreach (Exterior e in exteriors)
            {
                using (var client = new HttpClient())
                {
                    try
                    {
                        client.BaseAddress = new Uri("http://steamcommunity.com");
                        string uri = "/market/priceoverview/?currency=3&appid=730&market_hash_name=" + Query.Weapon.Name.Replace(" ", "%20") + "%20|%20" + Query.Name.Replace(" ", "%20") + "%20(" + e.Name.Replace(" ", "%20") + ")";
                        var response = await client.GetAsync(uri);
                        response.EnsureSuccessStatusCode(); // Throw in not success

                        var stringResponse = await response.Content.ReadAsStringAsync();
                        JObject data = JObject.Parse(stringResponse);

                        if (data["success"].Value<bool>())
                        {
                            if (data["lowest_price"] != null)
                            {
                                model = new PriceViewModel
                                {
                                    QuerySuccessful = true,
                                    ListingExists = true,
                                    ListingUrl = "http://steamcommunity.com/market/listings/730/" + Query.Weapon.Name + " | " + Query.Name + " (" + e.Name.Replace(" ", "%20") + ")",
                                    Price = data["lowest_price"].ToString()
                                };
                                PossibleExteriors[e] = model;
                            }
                            else
                            {
                                model = new PriceViewModel
                                {
                                    QuerySuccessful = true,
                                    ListingExists = false,
                                    ListingUrl = "http://steamcommunity.com/market/listings/730/" + Query.Weapon.Name + " | " + Query.Name + " (" + e.Name.Replace(" ", "%20") + ")",
                                    Price = ""
                                };
                                PossibleExteriors[e] = model;
                            }
                        }
                    }
                    catch
                    {
                        model = new PriceViewModel
                        {
                            QuerySuccessful = false,
                            ListingExists = false,
                            Price = ""
                        };
                        PossibleExteriors[e] = null;
                    }
                }
            }
            if (PossibleExteriors.Values.Any(x => x != null))
            {
                //return good model
            }
            else
            {
                //return empty
            }
        }
    }
    //return error
}

1 个答案:

答案 0 :(得分:0)

  

我想知道究竟是什么造成了这种情况,为什么ajax调用导致Action的并行执行?我怎么能强制ajax调用逐个运行或者做任何其他事情来解决这个问题。< / p>

你对异步调用有一个基本的误解。此JavaScript将触发请求,然后在获得响应之前继续进入循环的下一次迭代。每当异步调用完成时,无论何时发生以及发生的顺序,都将调用complete函数。这意味着新调用的到达速度快于应用程序返回结果的速度,因此它的工作不止一个一次请求。完全正常!

如果需要按特定顺序进行这些调用,为什么不将它们全部归为一个请求?将项列表传递到data属性并在C#中循环。

如果这必须是JavaScript中的循环,则需要等待来自异步调用的响应(基本上使其同步)如果要同步执行此调用,如调用GetPrice,获得响应,对响应做一些事情,然后进行下一次迭代并重复,你需要改变方法。

var $prices = $('.prices').map(function() {
    return new { Id: id, Exterior : exterior, Type : type }
});

getPrice($prices, 0);

function getPrice(prices, index) {
    $.ajax({
        type: "GET",
        url: "/Skin/GetPrice",
        data: prices[index] // if this were the whole prices list, you could do the loop in C# instead
        cache: false,
        dataType: "json",
    }).complete(function (data) {

       // do all that processing stuff

       index++;
       // if there are more prices to compute, call the function again
       if (prices.length - 1 >= index) {
           getPrice(prices, index);
       }
    });
}