41

Managing Complex Waiting Experiences on Web UIs

 5 years ago
source link: https://www.tuicool.com/articles/hit/M7fuiqB
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Managing Complex Waiting Experiences on Web UIs

W aiting is not a concept we like. We are usually stressed at every point where “waiting” touches our lives. And on the internet, “waiting” can be much more complicated than we thought it would be.

But apparently there is a long time we will have to “wait” until the tech guys solve the “speed” problem. ¯\_(ツ)_/¯

“You cannot manage what you cannot define.”

Part 1: Let’s define “waiting”!

On the Web, we frequently face the expression “loading” . I experienced that managing the “loading” experience is much more complicated than I thought, and I really had to manage it.

So, let’s define “waiting”:

In interfaces, “waiting” splits into 4 concepts which you can combine :

  1. Scope: Where the “waiting” happens.
  2. Specificity: If the “waiting” time is known.
  3. Interaction: If the “waiting” blocks the user or not.
  4. Reality: If the “waiting” is real or fake.

1. Scope

Defines where the “waiting” action happens. It may be two areas:

  • :package: Application [A]

    Whole application will be loaded or some loading will affect whole application. E.g. Booting an operating system, opening a big software.
  • :scissors: Component [C]

    A part of an application will be loaded. E.g. Loading timeline tweets while scrolling Twitter’s feed.

2. Specificity

Defines if we know then the “waiting” will end.

  • ⏭ Determinate [D]

    The waiting action has a specified ending. E.g. Downloading a file, watching a movie, listening to a music, etc.
  • :fast_forward: Indeterminate [I]

    The waiting action does not have an ending. E.g. Streaming a live TV channel, listening to a radio, waiting for someone to write a reply to your comment, sending a request to a server, etc.

3. Interaction

Defines if the “waiting” action will block the interaction origin (user).

  • :lock: Blocking [B]

    The waiting action is critical and the user shouldn’t touch specified area while something is happening. E.g. blocking user not to click “create” button again while creating something on back-end.
  • :unlock: Non-blocking [N]

    The waiting action is not really critical and user can touch anywhere while something is happening. E.g. Allowing user to step into a specified time while YouTube movie is loading.

4. Reality

Defines if the “waiting” action is real or not real.

  • :memo: Real [R]

    The waiting action really waits for something to end in the background. E.g. User uploads their avatar to the server.
  • :thought_balloon: Fake [F]

    The waiting action is not really waiting but it “feels” like doing something. It’s generally for UX purposes. E.g. Wait for server to create seed data.

“Waiting” Examples

Every combination of these 4 concepts has a value on UIs.

I don’t think to add Reality concept to the combination since it doesn’t make any difference on UI aspect.

Application, Determinate, Blocking :package: ⏭ :lock:

Use cases: Splash screens.

Think of an application scope with blocking user and has a predictable ending. It’s basically a splash screen.

Splash screens are something which puts users to on hold and it doesn’t allow you to use anything while things completely set up.

1*DBMdPjtlH4SofS43vP75Uw.png
Splash screen of NetBeans IDE.

In the example above, there is a progress bar that indicates the status of the waiting progress.

Info: If the “waiting” work has a predictable or specified ending (determinate) , generally “progress bars” are being used.

1*3v0quFQvwCHVpu4dz7exlA.gif
A progress bar goes from 0 to 100.

Application, Determinate, Non-blocking :package: ⏭ :unlock:

Use cases: Top loader, global activity indicator.

Blocking user is not friendly for your application and when the waiting is on application scope, top loaders or global activity indicators are your friend.

1*n3_oh7fr_3LkmyfMezxXXw.jpeg
YouTube’s global activity indicator.

Note: Predictable waitings should also be considered as “determinate” even they are “indeterminate”. A page loads in maximum 1–2 seconds. Thus it’s a good UX to use a progress bar.

Application, Indeterminate, Blocking :package: :fast_forward: :lock:

Use cases: Splash screens (for mobile)

1*TdXYWSJK3YBVJAY7XcqEgQ.png
Opening screen of Facebook Application

Waiting for an “indeterminate” action is generally shown as “activity indicators” which are circle loaders .

1*z0b320xFLqKpTTPqvKi6kw.gif
An activity indicator (circle loader) that goes nowhere.

Application, Indeterminate, Non-blocking :package: :fast_forward: :unlock:

Use cases: Activity indicator, hourglass.

When you do not want to block user while something is happening on application, an activity indicator shown on screen which is generally minimal.

1*wXHJ8CAL00UV6ibTUbd0VQ.png
An indeterminate network activity happening on iOS which is not blocking user.

Component, Determinate, Non-blocking :scissors: ⏭ :unlock:

Use cases: Background loaders, percentage texts.

While you actually wait for something to load, the UI will allow you to interact with it. YouTube’s “gray loader” actually covers this case.

1*dbdypf8PZumGmZb2wmzfkg.png
Gray loader of YouTube

Component, Indeterminate, Blocking :scissors: :fast_forward: :lock:

Use cases: Ghost loaders

Ghost loaders are most popular loaders nowadays. Building user interface with faking its content makes the layout more stable in UX aspect.

1*fYglrB29iOOND1C-J6Ry0g.gif
Slack’s ghost loaders.

Combinations without examples, not very common:

  • :scissors: ⏭ :lock: Component, Determinate, Blocking: Download progress bars of browsers may be examples for that.
  • :scissors: :fast_forward: :unlock: Component, Indeterminate, Non-blocking: Optimistic rendering with an activity indicator may be example for that.

Let’s summarize the combinations with a table:

1*8qwP36NaE1mpbenCMpg0Sw.png
Scope, Specificity, Interaction. Reality concept doubles this table.

Part 2: Let’s manage them!

After defining the concepts, managing them become easier.

Let’s assume we have an interface as below:

1*BJ2ssL8PUj35WcVukAkGAg.gif
An application scope top loader, and many component loaders.

There are few simple steps to easily manage them:

1. Name every “wait”:

Naming waits is the first step you need to make. It allows you to trace and debug in complex states.

1*LoXdH7fqxiEd-ZvUzoG5Mw.png
Write a clear message what it’s waiting for.

2. Collect them into a list:

The “waiting” names should be collected into an array:

Loaders should be in a global singleton loaders array. Also the names must be unique.

let waitingFor = [
"fetching sidebar",
"fetching user",
"fetching content",
"sending content",
];

3. Add and remove them:

A simple push to the waitingFor before the actual work starts:

// Start a new loader

waitingFor.push("logging in");
await fetch("/login");

And to remove, filter the waitingFor and replace it with the new state.

// End the loader
 
await fetch("/login");
<strong>waitingFor = waitingFor.filter(l => l != "logging in");</strong>

4. Get the state of loaders:

// Are there any loaders on application scope?

return waitingFor.length > 0;
// Are there any specified loader?

return waitingFor.includes("logging in");

5. Collect progresses in a key-value store:

Keep progress information in another global singleton object.

<strong>let progresses = {};</strong>

6. Starting a progress:

Also the waitingFor should be appended.

// Set the progress of "uploading avatar"
waitingFor.push("uploading avatar");
progresses["uploading avatar"] = { current: 249, total: 1828 };

7. Ending a progress:

waitingFor = waitingFor.filter(l => l != "uploading avatar");
const { ["uploading avatar"]: omit, ...progresses } = progresses;
// or
delete progresses["uploading avatar"];

A Vue.js Implementation: vue-wait

According the ideas above, I created a tool called “vue-wait” that manages your loaders with a declarative API and useful Vue component .

1*dUXkcBIh6oEL-a6NWhWxMA.png
vue-wait logo contains the V of Vue, X of Vuex and a circle indicator.

Vue-wait is an implementation for Vue to manage loaders easily. It has a very simple API.

1*FbzqfGiow9iTDX_pzM5xNw.gif
https://f.github.io/vue-wait/

For detailed documentation, please visit https://github.com/f/vue-wait

Thanks Fatih Acet for review.


Recommend

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK