Skip to content

Instantly share code, notes, and snippets.

@MuhammadQuran17
Last active March 18, 2026 07:44
Show Gist options
  • Select an option

  • Save MuhammadQuran17/8e9bfe7711474a9294af29464fec2a18 to your computer and use it in GitHub Desktop.

Select an option

Save MuhammadQuran17/8e9bfe7711474a9294af29464fec2a18 to your computer and use it in GitHub Desktop.
Js helpers
Aspect Promise.all Promise.allSettled
Rejects on first failure Yes, stops everything No, waits for all
Result on success Array of values Array of {status: "fulfilled", value: ...}
Result on mixed Rejects with first error Array with fulfilled/rejected statuses
Use case All must succeed (e.g., required API calls) Inspect all outcomes (e.g., optional fetches)

Promise.all rejects immediately if any promise rejects, returning only successful values if all succeed.
Promise.allSettled always resolves after all promises settle (fulfill or reject), providing status for each

Promise.all() allows multiple asynchronous operations to be initiated at almost the same time and run concurrently, which significantly reduces total execution time when tasks are independent

Promise.resolve

Promise.resolve() looks trivial, but it solves several very specific problems in asynchronous control flow and API design.


1. Normalize values into Promises

It guarantees: “whatever I have, I now treat it as a Promise.”

function maybeAsync(value) {
  if (Math.random() > 0.5) {
    return value;              // sync
  } else {
    return fetch(value);       // async (Promise)
  }
}

// Normalize:
Promise.resolve(maybeAsync('url'))
  .then(result => {
    // always safe: result comes through a Promise chain
  });

Without Promise.resolve, you’d need branching logic for sync vs async results.


2. Wrap non-Promise values into async chains

Promise.resolve(42).then(x => console.log(x));

This ensures the value runs through the microtask queue (async), not immediately.

This is important for consistent execution timing.


3. Flatten nested Promises (thenable resolution)

If you pass a Promise into Promise.resolve, it does not double-wrap:

const p = Promise.resolve(Promise.resolve(5));

p.then(console.log); // 5 (not Promise<Promise<5>>)

It "unwraps" automatically — this is part of the Promise resolution algorithm.


4. Start a Promise chain explicitly

Useful when you want to build a chain from scratch:

Promise.resolve()
  .then(() => step1())
  .then(() => step2())
  .catch(console.error);

This is cleaner than nesting or mixing sync/async logic.


5. Ensure async behavior (microtask scheduling)

Even if the value is already available, Promise.resolve defers execution:

console.log('A');

Promise.resolve().then(() => {
  console.log('B');
});

console.log('C');

// Output:
// A
// C
// B

This guarantees predictable ordering relative to other async tasks.


6. Interoperability with “thenables”

If you pass an object with a .then() method:

const thenable = {
  then(resolve) {
    resolve('hello');
  }
};

Promise.resolve(thenable).then(console.log); // "hello"

It converts “thenables” into real Promises.


When you actually need it

You typically use Promise.resolve() when:

  • You’re writing library / reusable code
  • You need to normalize sync + async inputs
  • You want consistent async execution
  • You’re building Promise chains dynamically

When you DON’T need it

Avoid unnecessary usage:

// redundant
Promise.resolve(fetch(url))

// better
fetch(url)

Mental model

Think of it as:

“Convert anything into a properly behaved Promise and schedule it in the async pipeline.”


Author: GPT-4o

In JavaScript, there are three primary ways to define functions: Function Declarations, Function Expressions, and Arrow Functions. Each has its own syntax, behavior, and use cases. Here’s a detailed explanation of the differences:

1. Function Declaration

Syntax:

function functionName(parameters) {
  // function body
}

Key Characteristics:

  • Hoisting: Function declarations are hoisted, meaning they are moved to the top of their scope during the compile phase. This allows you to call the function even before it is defined in the code.
  • Named Function: Always has a name (functionName), which is used to refer to the function.
  • this Binding: In regular functions, the value of this is determined by how the function is called (runtime binding).

Example:

console.log(add(2, 3)); // Outputs: 5

function add(a, b) {
  return a + b;
}

2. Function Expression

Syntax:

const functionName = function(parameters) {
  // function body
};

Key Characteristics:

  • Not Hoisted: Function expressions are not hoisted. This means that the function cannot be used before it is defined.
  • Anonymous Function: Can be anonymous (without a name) or named. If named, the name is only available within the function scope.
  • this Binding: Like function declarations, the value of this is determined at runtime by how the function is called.

Example:

const add = function(a, b) {
  return a + b;
};

console.log(add(2, 3)); // Outputs: 5
  • Error Example (Hoisting issue):
console.log(add(2, 3)); // Error: add is not defined

const add = function(a, b) {
  return a + b;
};

3. Arrow Function

Syntax:

const functionName = (parameters) => {
  // function body
};

Key Characteristics:

  • Shorter Syntax: Arrow functions provide a concise syntax for writing functions.
  • No this Binding: Arrow functions do not have their own this context. Instead, they lexically inherit this from the surrounding code, which means the value of this is determined by the surrounding (enclosing) context at the time the function is defined, not at runtime.
  • Cannot be Used as Constructors: Arrow functions cannot be used with the new keyword to create instances.
  • Implicit Return: If the function body contains a single expression, you can omit the {} and the return keyword, and the expression will be implicitly returned.

Example:

const add = (a, b) => a + b;

console.log(add(2, 3)); // Outputs: 5
  • Example with this:
function Person() {
  this.age = 0;

  setInterval(() => {
    this.age++; // `this` is lexically inherited from `Person`
    console.log(this.age);
  }, 1000);
}

const p = new Person(); // Will correctly increment `age` on the `Person` object
  • Error Example (Using new):
const Person = () => {};
const p = new Person(); // Error: Person is not a constructor

Summary of Differences

Feature Function Declaration Function Expression Arrow Function
Syntax function name() {} const name = function() {} const name = () => {}
Hoisting Yes No No
this Binding Dynamic (runtime) Dynamic (runtime) Lexical (inherited from context)
Usage as Constructor Yes Yes No
Anonymous Function No Yes (can be) Yes
Implicit Return No No Yes (if single expression)

Use Cases

  • Function Declaration: Best for defining functions that need to be available throughout a block or script, especially when hoisting is beneficial.
  • Function Expression: Useful when you need to create functions dynamically or when you want to control when and where the function is available.
  • Arrow Function: Ideal for concise functions, especially in callbacks or when working within a method where you want this to be inherited from the outer scope.

Understanding these differences helps in choosing the right type of function depending on the needs of your JavaScript code.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment