多个AJAX WebAPI异步调用到达控制器方法随机延迟

时间:2016-04-20 20:10:42

标签: c# ajax asynchronous asp.net-web-api concurrency

我有3个异步WebAPI,我在加载MVC页面的同时通过JQuery AJAX调用它。其中一个,有时两个或全部非常快地到达控制器方法,有时其中一个或两个延迟约3秒和10秒。每个异步方法的工作执行总是非常快(几毫秒)。我发现的唯一解决方案是禁用会话状态(这对我来说没有意义,因为它在WebAPI中默认禁用,但我已尝试但没有成功)并且我应该使用异步方法能够并行运行来自同一会话的所有3个请求,这正是我已经在做的事情。

我还试过,如果它是我正在使用的IIS Express,但IIS具有相同的效果。也尝试了各种浏览器但同样的问题。

我真的迷失在这里,有人有可能阻止我的请求的解决方案或想法吗?请记住,请求是随机阻止的,有时它很好,但大部分都没有,其他两个请求的延迟总是3秒和10秒。

this is how it looks like in the dev tools

我的客户端代码(所有3个调用都是这样的):



            $.ajax({
                type: "GET",
                url: "/api/follow/getFollows/" + this.userId,
                contentType: "application/json",
                dataType: "json",
                processData: false,
                success: (data) => {
                    this.handleLoadedFollows($("#followsList"), data);
                },
                error: (data) => { alert("error"); }
            });




我的async webAPI方法看起来像这样(所有3种方法都是这样的):

    [HttpGet]
    [Route("getFollows/{userId}", Name = "Follow.GetFollows")]
    public async Task<IHttpActionResult> GetFollows(Guid userId)
    {
        var entries = await _followService.GetFollowsAsync(userId, null, 20);

        // create viewmodel
        var viewModel = await _followViewModelFactory.CreateUserViewModelAsync(entries.Results);
        return Ok(viewModel);
    }

2 个答案:

答案 0 :(得分:1)

检查IIS日志后,我确信浏览器是这里的瓶颈。在彼此之后快速触发几个AJAX请求并不能很好地工作。这就是我遇到这些巨大延误的原因。

我通过使用超时机制来解决它,以确保不会立即针对浏览器触发所有请求。

我正在使用打字稿但这里是我的解决方案(可能不是最好的解决方案,但它有效)

我创建了一个处理程序,它对函数调用进行排队并使用指定的超时执行它们:

module Utilities {
    export class AjaxRequestHandler {
        private static ajaxQueue: Function[] = [];
        private static queueFunctionExecuted: boolean[] = [];

        static enqueueAjaxRequest(ajaxFunction: Function): void {
            this.ajaxQueue.push(ajaxFunction);
            this.queueFunctionExecuted.push(false);

            var interval = setInterval($.proxy(() => {
                if (this.ajaxQueue[0] === ajaxFunction && this.queueFunctionExecuted[0] === false && this.queueFunctionExecuted.length > 0) {
                    ajaxFunction();
                    this.queueFunctionExecuted[0] = true;

                    setTimeout($.proxy(() => {
                        this.ajaxQueue.shift();
                        this.queueFunctionExecuted.shift();
                    }, this), 100);
                }
            }, this, ajaxFunction)
                , 20);

            setTimeout($.proxy(() => {
                clearInterval(interval);
            }, interval), 10000);
        }
    }
}

并且函数的排队是这样的:

        Utilities.AjaxRequestHandler.enqueueAjaxRequest($.proxy(this.getFollowedBy, this));
        Utilities.AjaxRequestHandler.enqueueAjaxRequest($.proxy(this.getFollows, this));
        Utilities.AjaxRequestHandler.enqueueAjaxRequest($.proxy(this.getSingleFollows, this));

希望这可以帮助有同样问题的人

答案 1 :(得分:0)