0

I have tried ways to search for a solution but I can't seem to find the right combination of words or something... here goes:

I have an ASP.NET MVC application that users scan inventory/package barcodes into. Every time someone scans an item, I make an async request and then display a popup message with information about the package. This part works as expected and does not block the application during the request:

$.ajax({
                            type: 'GET',
                            dataType: 'json',
                            async: false,
                            url: '@Url.Action("SingleOrderLookup")?trackingNumber=' + trackingId,
                            success: function (result) {

                                if (result.success) {

                                    var audio = findAudio(result.model, audioClips, saturdayAudio);
                                    suppressDefaultSound = true;

                                    var titleText = result.model.displayPromptText;
                                    if (result.model.isRefrigerated) {
                                        isRefrigerated = true;
                                        titleText = "<p style='color: blue;'>(REFRIGERATED)</p>" + "<p>" + result.model.displayPromptText + "</p>";
                                    }

                                    swal.fire({
                                        title: titleText,
                                        text: "Place in route for " + result.model.displayPromptText,
                                        type: "success",
                                        showCancelButton: false,
                                        confirmButtonText: "Sorted",
                                        cancelButtonText: "Cancel",
                                        timer: 1750,
                                        preConfirm: function () {
                                            return new Promise(function (resolve) {
                                                resolve();
                                            }, 1000);
                                        }
                                    }).then(result => {
                                        if (result.value) {

                                        }
                                    });

                                    var dupe = findOrderByTrackingNumber(trkNumbers, result.model.trackingId);
                                    if (!dupe) {
                                        trkNumbers.push({ trackingNumber: trackingId, depotId: result.model.destinationHub });
                                        pkgCount++;
                                        if ($("#divUpdatePickup").is(":hidden"))
                                            $("#divUpdatePickup").show();
                                        AddLogToTable(trackingId);
                                    } else {
                                        //audible feedback that duplicate was scanned
                                        //if (!trkBin) PlayAudio(2);
                                        //PlayAudio(2);
                                    }

                                    //playing audio
                                    if (isRefrigerated) {
                                        setTimeout(function () {
                                            if (audio) playByteArray(audio);
                                        }, 1500);

                                        PlayRefrigerate();
                                    } else {
                                        if (audio) playByteArray(audio);
                                    }

                                }

                                if (result.nullRoute) {
                                    addToTrkNumbers = false;

                                    Swal.fire({
                                        title: "NO ROUTE DEFINED",
                                        text: "Unable to match order to a route!",
                                        type: "warning",
                                        showCancelButton: false
                                    });
                                }
                            }
                        });

However, I want the page to make another async call to populate a variable with an array of objects, transparently and without blocking the user from making scans and receiving information back from the async calls from the above code. This call should occur immediately when the page is loaded, and it could take more than a minute or two to receive all the data expected from this call. Once the response is back, the collection variable (zipSort[]) should be populated. The data in this variable will contain a "cache" of elements that the page can query against to avoid having to make individual server-side calls after each scan (in essence, I want to "front-load" data needed for the scan events and once completed, individual calls to the server should not be necessary since this variable should contain 99% of the IDs expected to be scanned).

This is where I'm having an issue and it's probably due to a lack of understanding of how async calls/JS promises work. Here is the code I have so far for this:

//array to hold data on expected tracking number scans
var zipSort = []


    async function getCheckinGroup(zipSort) {
        console.log("Fetching complete check-in group...");
        var url = '/SortFacility/HubManager/GetOrders';
    
        var promise = new Promise((resolve,reject) => {
    
            $.ajax({
                type: "GET",
                url: url,
                cache: false,
                async: true,
                contentType: "application/json",
                success: function (result) {
                    if (result.success) {
                        console.log("Retrieval success");
                        try {
                            zipSort = result.model;
                            resolve(result.model);
                        } catch (ex) {
                            reject("Some error?");
                        }
                    } else {
                        reject("Some error?");
                    }
                },
                error: function (ob, errStr) {
                    reject("Something went wrong");
                }
            });
        });
    
        return promise;
    }
    
    //don't want this to hold up execution of the rest of the code, so zipSort[] should
    //remain empty and get set transparently when the ajax response is returned:
    getCheckinGroup(zipSort);

Every version of code I'm trying out from articles and tutorials I have read holds up the UI and keeps users from being able to scan items while the response hasn't been returned. What am I missing? How should I change this so that (a) users can begin scanning immediately once the page has loaded and receive information from individual async calls to the DB, and (b) zipSort[] can be populated with the totality of any data potentially needed for these scans, and once populated, scan events trigger a lookup on that variable instead of continued individual calls to the database?

Any help would be appreciated!

Edit: tried simply adding this call in-line and no matter where I put it, it blocks the other code from running until response is received, even though async is set to true:

$.ajax({
                type: "GET",
                url: url,
                cache: false,
                async: true,
                contentType: "application/json",
                success: function (result) {
                    console.log("Data received.");
                    zipSort = result.model;
                }
            });
  • I'm a little confused; the one you said doesn't block you have async set to false (and a 1-second delay somewhere in there). You mark the second function async but have no await in it (and the ajax call is explicitly async, which is correct). Is there any other context we might need to be aware of? An async Ajax call won't block without a reason. – Dave Newton Jul 23 '21 at 22:47
  • That's a good point - those individual calls don't take very long, so I'm guessing this is why I was under the impression that part was working asynchronously. So this part was only added to give context as to code I want to be able to execute while the other, larger, async call is taking place. I didn't include an await on the second call because I "don't" want to await anything or block the code. This is where I think I am confused. Why include "await" if it shouldn't block the other functions? – FunkiNATEr Jul 23 '21 at 22:53
  • Seems like ajax has promises implemented, [this article](http://michaelsoriano.com/working-with-jquerys-ajax-promises-and-deferred-objects/) might be of help – Fernando Bravo Diaz Jul 23 '21 at 22:54
  • My point about async was why to include async if there's no await? Its only use use to mark functions that use await. – Dave Newton Jul 23 '21 at 23:41
  • I have tried w/ & w/o async. It always blocks the other ajax calls. This ajax call could take up to five minutes, but until that finishes, users should be able to perform scans and receive a response from the "individual" ajax calls within ~1 second. This isn't happening. It's waiting until the SECOND function completes and I don't want that, but async or not, I can't get the @#$@$# thing to just load in the background. I have created a simple method in the controller that just returns a value after waiting 30 seconds until I figure this out. Scans don't produce output until after 30 seconds. – FunkiNATEr Jul 24 '21 at 00:15

1 Answers1

0

Thanks everyone for your help. I found this little gem, which solved my problem:

https://josef.codes/c-sharp-mvc-concurrent-ajax-calls-blocks-server/

Applying [SessionState(System.Web.SessionState.SessionStateBehavior.Disabled)] to my controller class enabled concurrent async ajax calls.