I’m trying to figure out how Promises work with multiple HTTPS requests in Javascript, but I have a problem where the results seem out of order with the request sequence. I’m using an ASP.NET Controller API implementation for a simple calculator, and Javascript to access the API. I seem to have a synchronization issue, but I can’t for the life of me work out why.
The CalculatorController
:
using Microsoft.AspNetCore.Mvc;
namespace Wolflight.Calculator.Controllers
{
[ApiController]
[Route("[controller]")]
public class CalculatorController : Controller
{
private const string TotalName = "Total";
private decimal RetrieveTotal()
{
return ToDecimal(HttpContext.Session.GetString(TotalName));
}
private void StoreTotal(decimal value)
{
HttpContext.Session.SetString(TotalName, FromDecimal(value));
}
private static string FromDecimal(decimal value)
{
return value.ToString();
}
private static decimal ToDecimal(string? value)
{
if (value != null)
{
return Decimal.Parse(value);
}
else
{
return 0M;
}
}
[HttpGet()]
[Route("/api/Calculator/Total")]
public decimal? GetTotal()
{
return RetrieveTotal();
}
[HttpPut()]
[Route("/api/Calculator/Add")]
public void AddValue(decimal value)
{
StoreTotal(RetrieveTotal() + value);
}
[HttpPut()]
[Route("/api/Calculator/Subtract")]
public void SubtractValue(decimal value)
{
StoreTotal(RetrieveTotal() - value);
}
[HttpPut()]
[Route("/api/Calculator/Multiply")]
public void MultiplyValue(decimal value)
{
StoreTotal(RetrieveTotal() * value);
}
[HttpPut()]
[Route("/api/Calculator/Divide")]
public void DivideValue(decimal value)
{
StoreTotal(RetrieveTotal() / value);
}
}
}
The site.js
:
const uriBase = "/api/Calculator/";
const uriTotal = uriBase + "Total";
const uriAdd = uriBase + "Add";
let GetTotalValuePromise = function () {
return new Promise(function (myResolve, myReject) {
let total = fetch(uriTotal)
.then(response => response.text())
.catch(error => myReject('Unable to get total.', error));
myResolve(total);
})
};
let PutAddValuePromise = function (addValue) {
return new Promise(function (myResolve, myReject) {
fetch(uriAdd + '?value=' + addValue, { method: 'PUT' })
.catch(error => myReject('Unable to add value.', error));
myResolve();
}
)
};
function DisplayTotal(total) {
const tBody = document.getElementById('totalDisplay');
tBody.innerHTML = total;
}
function GetTotal() {
UpdateDisplay();
}
function AddValue() {
let value = document.getElementById('addValue').value;
PutAddValuePromise(value)
.then(function () {
UpdateDisplay();
});
}
function UpdateDisplay() {
GetTotalValuePromise()
.then(
function (total) { DisplayTotal(total); },
function (message, error) { console.error(message, error); }
)
}
When I call AddValue()
from a form button, the result is that sometimes the /Total
call returns the value before the /Add
occurs, and sometimes it returns the result after.
e.g.
Total
=0
- Call
AddValue
, with elementaddValue
as 5.
Network Requests:
/Add?value=5
(no response)/Total
– Response:0
.
OR
Network Requests:
/Add?value=5
(no response)/Total
– Response:5
.
Am I missing something in how Promises work, or is the problem on the server side?
If I call GetTotal
manually after the AddValue
, it always returns the correct value.