flow.if()
Using flow.if(), filter out triggers from the callback pipeline.
Syntax
flow.if(callback);
Parameters
- callback
- The callback to add onto the callback pipeline. If it returns something truthy, the trigger is let through to the next callback in the pipeline. Otherwise, the trigger is stopped and removed from the pipeline. The callback receives the trigger arguments as arguments, just like other pipeline-related methods, like
.then()
do.
Return value
The same Flow
object the method was called on, allowing for method chaining.
Examples
The .if() method is primarily useful in two cases; either the flow is passed to another function (such as live.link()
) or the rest of the callback pipeline is non-linear (e.g. using .throttle()
, .once()
or .pipe()
). Let's do an example for either of these cases.
Link to localStorage
When binding a live variable to an item in localStorage, generally it is desired to keep it up-to-date even if this item changes in a different tab or browsing context. The window object emits a storage event, but this event fires for all changes to localStorage, and even for other types of storage such as sessionStorage. To avoid our live.link()
from unnecessarily running updates, we can use .if() to limit the amount of triggers passed to our link.
live.link($.$username, {
get: () => localStorage.getItem('username'),
set: value => localStorage.setItem('username', value),
changes: when(window).storages().if(event => {
const { storageArea, key } = event;
return storageArea == localStorage && key == 'username';
})
});
The flow passed to live.link() now triggers only when the storage type is localStorage and when the key changed is 'username'. The link thus runs the getter much less often, resulting in better performance.
Await enter key
Let's write a simple async version of the native window.prompt(). We'll add an <input> element to the document (ignoring styling for the sake of the example). Our asyncPrompt() function is to return a value after the user presses the 'Enter' key. To write our code nice and sequentially, we'll use when()
to listen for keydown events, and use .once()
to stop the listener after it has fired. We'll need to use an .if() before the .once() call to make sure our await expression only resolves when we press the 'Enter' key, instead of just any key.
async function asyncPrompt(){
const input = document.createElement('input')
document.body.append(input)
await when(input).keydowns()
.if(event => event.key == 'Enter')
.once()
input.remove()
return input.value
}
Note that .until()
wouldn't quite work here, because once its callback returns something truthy, it stops the flow immediately, preventing the await expression from ever resolving. On the other hand, .once() allows a single received trigger to run through the rest of the callback pipeline, making it perfect for this case in conjunction with .if()
.
Usage notes
If the callback pipline is linear apart from the .if() call, then the .if() method could be replaced by a regular if statement. For example, when writing .if().then(), we can instead remove the .if() method, and wrap our .then() callback with a regular if() statement (or start it with an early return). The latter is usually a bit simpler to understand and maintain and is therefore recommended where applicable.
See also