Reputation: 73
Recently, I have had need of designing an improved reporting system for generation of large reports.
The issue with the old system was how long the browser would hang on the request waiting for the file to be ready. If it took too long, the request would be timed out.
To avoid this, and make for a better UI, I have designed the following process:
I was a bit rusty with Async, so a lot of my work was following by example. However, the final result I thought should work generated the following result:
9:23:51 AM
9:23:51 AM
before ping
ping 9:23:51 AM
Your file is not ready for download...
null
ping 9:23:56 AM
Your file is not ready for download...
ping 9:23:57 AM
Your file is not ready for download...
ping 9:23:58 AM
Your file is not ready for download...
The file creation would go off async and generate the file. But as soon as something else was awaited (the ping), the entire process would hang until the file was created, and then the ping logic would loop as desired.
My first attempt at a solution was not awaiting the ping either. However, I would be left with a promise I could not read to get the response of the ping out of.
The final solution I realized after a nights sleep was the ping call must be calling the same thread currently locked by the file creation. So I wrapped the whole file creation logic in a Task which achieved the result I desired.
However, whilst I have a solution, I still would like to understand the problem more.
Thank you for reading.
Code:
document.getElementById("btnGo").onclick = async function (e) {
await LaunchReport(btn.attributes["bespokeReport"].value);
};
async function LaunchReport(report) {
let fileName = await AjaxRequest("GenerateFileName", { report: report });
let reportData;
switch (report) {
case "StandardReport": {
console.log(new Date().toLocaleTimeString("en-US"));
AjaxRequest("RunStandardReport", { fileName: fileName }).then(console.log);
console.log(new Date().toLocaleTimeString("en-US"));
break;
}
default: {
//error logic
}
}
console.log("before ping");
await PingReport(fileName);
console.log("after ping");
}
async function PingReport(fileName) {
let response = await AjaxRequest("PingReportStatus", { fileName: fileName });
console.log("ping " + new Date().toLocaleTimeString("en-US"));
console.log(response);
if (response != "ready") {
await new Promise(resolve => setTimeout(resolve, 1000));
await PingBespokeReport(fileName);
} else {
window.alert(response);
}
}
async function AjaxRequest(action, data = null) {
let r;
await $.ajax({
type: "POST",
contentType: "application/json; charset=utf-8",
data: JSON.stringify(data),
dataType: "json",
url: "/admin/reports.aspx/" + action,
async: true,
success: function (res) { r = res.d; },
error: function (res) {
console.log(res);
r = res.d;
}
});
return r;
}
The site is a .NET Framework 4.6.1 site.
<WebMethod>
Public Shared Sub RunStandardReport(fileName As String)
Thread.Sleep(5000)
''Generate File Logic
End Sub
<WebMethod>
Public Shared Function PingReportStatus(fileName As String) As String
Try
Dim fileReady As Boolean = File.Exists("FileDirectory..." & "\" & fileName)
If fileReady Then
Return "ready"
Else
Return "Your file is not ready for download..."
End If
Catch ex As Exception
Return "There was a problem looking for your file with the name: " & fileName
End Try
End Function
Upvotes: 0
Views: 243