Async actions appear to be out of order
See original GitHub issueI’m trying to use async actions. For simplicity, I’m using only a single action, called update
, and dispatching all app actions through that. I’m also using the load
and update
events to set a state value on app startup and print the value on every state change, respectively.
Here’s the code:
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Hyperapp Async Test</title>
</head>
<body id="root">
<script src="https://unpkg.com/hyperapp"></script></script>
<script>
var { app, h } = hyperapp;
var initModel = 0;
// Helper to create an action payload in the correct shape.
function payload(key, value) { return { key: key, value: value }; }
function view(state, { update }) {
return h("div", {}, [
h("p", {}, "Current value: " + state.model),
h("button",
{ onclick: _ => update(payload("increment")) },
"Increment") ]);
}
function update(state, _, payload) {
return function(update2) {
switch (payload.key) {
case "edit":
return Promise.resolve({ model: payload.value }).then(update2);
case "increment":
return Promise.resolve({ model: state.model + 1 }).then(update2);
case "log":
console.log(payload.value);
return Promise.resolve(state).then(update2);
}
};
}
var events = {
load: function(_, { update }) {
// Set the value to 5 when the app loads.
return update(payload("edit", 5));
},
update: function(_, { update }, nextState) {
// Log the value whenever it changes.
return update(payload("log", nextState));
}
};
app({
state: { model: initModel },
view: view,
actions: { update: update },
events: events
});
</script>
</body>
</html>
I’m having two problems:
-
State updates appear out of order. First
state
is{ model: 5 }
, then it’s{ model: 0 }
, while my understanding is it should be the other way round. -
State seems to become
{ model: undefined }
after theload
event fires, so the view renders asCurrent value: undefined
, and clicking the Increment button logsObject { model: NaN }
.
Any suggestions on fixing these async updates? Thanks
Issue Analytics
- State:
- Created 6 years ago
- Comments:6 (2 by maintainers)
Top Results From Across the Web
JavaScript nested async function calls executed out of order
Some context: I'm trying to implement a functionality on a website that opens a panel on the left side, then inserts a form...
Read more >Question on the order of actions, especially async actions. #602
Now I understand it. Basically, the orders of actions are determined by the time when a program dispatches (async) actions, not by the...
Read more >Redux Fundamentals, Part 6: Async Logic and Data Fetching
The official Redux Fundamentals tutorial: learn how to use async logic with Redux.
Read more >Async actions in bare Redux with Thunk or custom middleware
Learn how to manage asynchronous actions in React apps with Redux Toolkit, or a bare Redux implementation with custom middleware.
Read more >async function - JavaScript - MDN Web Docs - Mozilla
The async function declaration declares an async function where the await keyword is permitted within the function body. The async and await ......
Read more >
Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free
Top Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
How could we determine if the state changed or not? We could check if
appState
holds the same reference or if it’s a new reference, and if it’s the same skip the update, already talked about here and the consensus was to let you have it.OK, I figured it out. The key is something similar to what @andyrj said–instead of returning a call to update with the existing state from the
"log"
case, I changed it to returnundefined
. It seems that theupdate
function in async updates (which I calledupdate2
above to avoid ambiguity) will force a state update even if the state value hasn’t changed. In turn, this will trigger myupdate
event handler, which will call theupdate
action, which will force a state update again, and so on, ad infinitum. Neat little infinite loop.TL;DR: avoid potential infinite loop by not calling the async
update
function if the state hasn’t actually changed.