What is the meaning of lazy evaluation in this comment?
A thunk is a function that takes no arguments and returns something (or does something as a side effect). Lazy evaluation is the process of deferring the evaluation of an expression until later, and this can be done with thunks:
// Not lazy
var value = 1 + 1 // immediately evaluates to 2
// Lazy
var lazyValue = () => 1 + 1 // Evaluates to 2 when lazyValue is *invoked*
You can also make return values lazy:
// Not lazy
var add = (x, y) => x + y
var result = add(1, 2) // Immediately evaluates to 3
// Lazy
var addLazy = (x, y) => () => x + y;
var result = addLazy(1, 2) // Returns a thunk which *when evaluated* results in 3.
Finally we can defer some asynchronous action:
// Not lazy
var callApi = spec => fetch(spec.url, spec.options);
// Immediately returns a Promise which will be fulfilled when the network response is processed.
var result = callApi({url: '/api', options: {}});
// Lazy
var callApiLazy = spec => () => fetch(spec.url, spec.options);
var result = callApiLazy({url: '/api', options: {}});
// result is a thunk that when evaluated will return a Promise ...
// which will be fulfilled when the network response is processed.
Now a thunk does not have to take zero arguments - you could return a lazy value that requires more arguments to successfully evaluate. This is properly known as "currying":
// Curried add (not lazy)
var add = x => y => x + y
var add3 = add(3)
var result = add3(7) // Immediately evaluates to 10
redux-thunk lets you return functions, rather than objects, as actions and invokes your function with a dispatch
function. You can then lazily produce an action (or actions) either synchronously or asynchronously. Most of the time, you would want to use this to allow you to dispatch asynchronously.
See also:
- http://www.datchley.name/currying-vs-partial-application/
Normally, Redux action creators are synchronous, meaning that, when you call them, you would expect them to return an Action and the Reducers to be called immediately and the state to change on the fly. You also expect this process to be really fast, because nothing but a small CPU-bound operation would be performed.
However, sometimes you want your action creator to go to the server, or do some non-CPU bound operation that would take a while. That's when it makes sense to return a function instead.
When your action creator returns a function, it returns immediately. From the perspective of who calls the action creator, nothing strange happened. Everything is as usual. But internally, instead of returning the Action object, your action creator returned a function like this..
function DoSomethingAsync() {
return (dispatch) => {
// go do something realllly slowly.
// ok now get the RESULT and call a regular action
dispatch(mySyncAction(RESULT));
}
}
Normally DoSomethingAsync
would return an Object
. What the Redux-Thunk
middleware does is to detect that a function was returned instead.. So, it does nothing but to call this function passing the same dispatch
as usual.
Now it's responsability of the callback to call dispatch
to dispatch a SYNC action.