admin管理员组文章数量:1332881
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.
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.
2 Answers
Reset to default 1You could try this below code. The issue you're facing this issue becaus new vlaue i snot being saved in the session and it is restyrning the old value before that.
To resolve this, add HttpContext.Session.CommitAsync().Wait() to ensure that the session state is persisted immediately after updating the total. use async/await in the clinetside code to execute the requests in the correct order, ensuring that the total is fetched only after the server has completed updating it.
Updated server-side code:
using Microsoft.AspNetCore.Mvc;
namespace CalculatorAPI.Controllers
{
[ApiController]
[Route("api/[controller]")]
public class CalculatorController : Controller
{
private const string TotalName = "Total";
private decimal RetrieveTotal()
{
var value = decimal.TryParse(HttpContext.Session.GetString(TotalName), out var total) ? total : 0M;
Console.WriteLine($"RetrieveTotal: {value}");
return value;
}
private void StoreTotal(decimal value)
{
Console.WriteLine($"StoreTotal: {value}");
HttpContext.Session.SetString(TotalName, FromDecimal(value));
HttpContext.Session.CommitAsync().Wait(); // Ensure session state is persisted
}
private static string FromDecimal(decimal value)
{
return value.ToString();
}
[HttpGet("Total")]
public ActionResult<decimal> GetTotal()
{
return RetrieveTotal();
}
[HttpPut("Add")]
public IActionResult AddValue([FromQuery] decimal value)
{
StoreTotal(RetrieveTotal() + value);
return Ok();
}
[HttpPut("Subtract")]
public IActionResult SubtractValue([FromQuery] decimal value)
{
StoreTotal(RetrieveTotal() - value);
return Ok();
}
[HttpPut("Multiply")]
public IActionResult MultiplyValue([FromQuery] decimal value)
{
StoreTotal(RetrieveTotal() * value);
return Ok();
}
[HttpPut("Divide")]
public IActionResult DivideValue([FromQuery] decimal value)
{
if (value == 0)
return BadRequest("Cannot divide by zero.");
StoreTotal(RetrieveTotal() / value);
return Ok();
}
}
}
Client-side JavaScript:
const uriBase = "https://localhost:7262/api/Calculator/";
const uriTotal = uriBase + "Total";
const uriAdd = uriBase + "Add";
async function GetTotalValue() {
try {
const response = await fetch(uriTotal);
if (!response.ok) {
throw new Error('Failed to fetch total');
}
const total = await response.json(); // Parse the response as JSON
return total;
} catch (error) {
console.error("Error getting total:", error);
}
}
async function AddValue() {
const value = document.getElementById('addValue').value;
if (!value) {
alert("Please enter a value to add.");
return;
}
try {
const response = await fetch(`${uriAdd}?value=${value}`, { method: 'PUT' });
if (!response.ok) {
throw new Error('Failed to add value');
}
await UpdateDisplay(); // Refresh the display after updating the total
} catch (error) {
console.error("Error in AddValue:", error);
}
}
async function UpdateDisplay() {
const total = await GetTotalValue();
if (total !== undefined) {
document.getElementById('totalDisplay').innerText = total; // Update the total display
}
}
Program.cs:
builder.Services.AddDistributedMemoryCache(); // Required for session state
builder.Services.AddSession(options =>
{
options.IdleTimeout = TimeSpan.FromMinutes(30); // Set session timeout
options.Cookie.HttpOnly = true;
options.Cookie.IsEssential = true; // Essential cookies for session
});
let PutAddValuePromise = function (addValue) {
return new Promise(function (myResolve, myReject) {
const response = fetch(uriAdd + '?value=' + addValue, { method: 'PUT' })
.catch(error => myReject('Unable to add value.', error));
myResolve(response);
}
)
};
本文标签: javascriptChained https requests using promises seem to be out of orderStack Overflow
版权声明:本文标题:javascript - Chained https requests using promises seem to be out of order - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1742314639a2451569.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
fetch().then()
etc. – Jeremy Lakeman Commented Nov 21, 2024 at 4:46