Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

Sorry, you do not have permission to ask a question, You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please type your username.

Please type your E-Mail.

Please choose an appropriate title for the post.

Please choose the appropriate section so your post can be easily searched.

Please choose suitable Keywords Ex: post, video.

Browse

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

Querify Question Shop: Explore Expert Solutions and Unique Q&A Merchandise

Querify Question Shop: Explore Expert Solutions and Unique Q&A Merchandise Logo Querify Question Shop: Explore Expert Solutions and Unique Q&A Merchandise Logo

Querify Question Shop: Explore Expert Solutions and Unique Q&A Merchandise Navigation

  • Home
  • About Us
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • About Us
  • Contact Us
Home/ Questions/Q 3849

Querify Question Shop: Explore Expert Solutions and Unique Q&A Merchandise Latest Questions

Author
  • 61k
Author
Asked: November 26, 20242024-11-26T06:31:08+00:00 2024-11-26T06:31:08+00:00

How to handle loading progress flicker

  • 61k

One of the most important things in our web apps UX is to provide a form of feedback when the app needs more time to process the user's action when e.g an ajax request is fired in the background. This is usually done using a progress bar, a spinner, or a combination of both.

Have you ever noticed though a “flaky” behavior when a lot of API calls happen at the same time?

Image description

We can provide a smooth experience to our users, so let's fix that!

What we'll build

We'll create a simple loader handler function for Promises that will make sure our loading indicator will disappear only when the last unresolved Promise gets resolved. We'll also make sure that the function is reusable so that it can be used with any project and with any progress loading indicator plugin.

Implementation

createLoader.ts

export const createLoader = (options: {   start: () => void;   end: () => void;   inc?: () => void;   slackTime?: number; }) => {   const promises: Promise<unknown>[] = [];    const opts = {     ...{       inc: () => {},       slackTime: 0,     },     ...options,   };    const load = <T>(promise: Promise<T> | (() => Promise<T>)) => {     const p = typeof promise === 'function' ? promise() : promise;      !promises.length && opts.start();     promises.push(p);      p.finally(() => {       setTimeout(() => {         promises.pop();         !promises.length ? opts.end() : opts.inc();       }, opts.slackTime);     });      return p;   };    return { load }; }; 
Enter fullscreen mode Exit fullscreen mode

We created a factory function that takes an options object as a parameter. The options object defines which operations will be performed on loading start/end and optionally an operation to execute when a Promise is resolved.

We can also define a slackTime that will be used as a delay to wait until the last Promise is resolved. This is useful in cases that we have e.g an API call that starts shortly after another call has just finished, causing a “flickering” effect in our loader.

The factory function will return our load method which will accept a Promise or a function that returns a Promise. Instead of firing our async functions directly, we'll pass them through our load function instead. Our loader then will make sure that the loading progress ends when the last of the Promises is resolved.

Options

Option Description Type Default
start A function to execute on loading start, this is where we start our progress loader function undefined
end A function to execute when loading ends, this is where we stop our progress loader function undefined
inc An optional function to execute when a promise resolves (valid for all promises except the last one). We can use this function to increment our loading progress. function () => {}
slackTime Time in ms to wait until last promise is resolved as to enable multiple operations in a sequence without re-triggering a loader progress start Number 0

Creating our loader

It's time to create our loader. Here we're using the popular nprogress library for our progress loading indicator as an example.

loader.ts

import NProgress from 'nprogress'; import { createLoader } from './createLoader';  NProgress.configure({   minimum: 0.35,   speed: 300, });  const start = () => {   NProgress.start(); };  const end = () => {   NProgress.done(); };  const inc = () => {   NProgress.inc(0.05); };  const loader = createLoader({ start, end, slackTime: 350, inc });  export const { load } = loader; 
Enter fullscreen mode Exit fullscreen mode

We have configured the NProgress instance and setup a new loader that will start, end, or increment the nprogress progress bar depending on the Promises' state.

How to use

Using our loader is fairly simple, we just need to pass our Promises into the load function and our loader will take care of the rest. Here's an example using axios that dispatches two requests so that they get registered in our loader.

import { load } from './loader'; import axios from 'axios';  const res1 = load(axios.get(`https://jsonplaceholder.typicode.com/todos`)); const res2 = load(axios.get(`https://jsonplaceholder.typicode.com/todos/1`)); 
Enter fullscreen mode Exit fullscreen mode

That's it, no more loading progress flicker!

If you want to see how this feels in a browser, checkout a live example of the loader that implements a global page progress bar (and some extra stuff too) in this stackblitz here

Make sure you open this with a Chromium-based browser (e.g Chrome) and run npm run dev on the console.

Update:
promise-loading-handler is now an npm package. You can include it in your JS project with npm install promise-loading-handler

Thanks for reading.

javascripttypescriptuxwebdev
  • 0 0 Answers
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

Sidebar

Ask A Question

Stats

  • Questions 4k
  • Answers 0
  • Best Answers 0
  • Users 2k
  • Popular
  • Answers
  • Author

    ES6 - A beginners guide - Template Literals

    • 0 Answers
  • Author

    Understanding Higher Order Functions in JavaScript.

    • 0 Answers
  • Author

    Build a custom video chat app with Daily and Vue.js

    • 0 Answers

Top Members

Samantha Carter

Samantha Carter

  • 0 Questions
  • 20 Points
Begginer
Ella Lewis

Ella Lewis

  • 0 Questions
  • 20 Points
Begginer
Isaac Anderson

Isaac Anderson

  • 0 Questions
  • 20 Points
Begginer

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help

Footer

Querify Question Shop: Explore Expert Solutions and Unique Q&A Merchandise

Querify Question Shop: Explore, ask, and connect. Join our vibrant Q&A community today!

About Us

  • About Us
  • Contact Us
  • All Users

Legal Stuff

  • Terms of Use
  • Privacy Policy
  • Cookie Policy

Help

  • Knowledge Base
  • Support

Follow

© 2022 Querify Question. All Rights Reserved

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.