A polyfill is a piece of code that provides functionality that is not natively supported in a browser or environment. In this case, we'll create a basic polyfill for the Promise object in JavaScript. Promises are a part of the ES6 specification, so if you're working in an environment that doesn't support ES6 promises, you can use a polyfill to add support.
Here's a simple implementation of a Promise polyfill along with an explanation of the code:
// Check if the Promise object is already defined in the environment
if (typeof Promise === "undefined") {
// Define a constructor function for the Promise object
function Promise(executor) {
// Create internal state variables
this.state = 'pending';
this.value = undefined;
this.onFulfilledCallbacks = [];
this.onRejectedCallbacks = [];
// Define resolve and reject functions
const resolve = (value) => {
if (this.state === 'pending') {
this.state = 'fulfilled';
this.value = value;
this.onFulfilledCallbacks.forEach(callback => callback(value));
}
};
const reject = (reason) => {
if (this.state === 'pending') {
this.state = 'rejected';
this.value = reason;
this.onRejectedCallbacks.forEach(callback => callback(reason));
}
};
// Execute the executor function with resolve and reject as arguments
try {
executor(resolve, reject);
} catch (error) {
reject(error);
}
}
// Define the `then` method
Promise.prototype.then = function (onFulfilled, onRejected) {
if (this.state === 'fulfilled') {
if (typeof onFulfilled === 'function') {
return new Promise((resolve) => {
resolve(onFulfilled(this.value));
});
} else {
return new Promise((resolve) => {
resolve(this.value);
});
}
}
if (this.state === 'rejected') {
if (typeof onRejected === 'function') {
return new Promise((resolve, reject) => {
reject(onRejected(this.value));
});
} else {
return new Promise((resolve, reject) => {
reject(this.value);
});
}
}
if (this.state === 'pending') {
return new Promise((resolve, reject) => {
if (typeof onFulfilled === 'function') {
this.onFulfilledCallbacks.push((value) => {
try {
resolve(onFulfilled(value));
} catch (error) {
reject(error);
}
});
} else {
this.onFulfilledCallbacks.push(resolve);
}
if (typeof onRejected === 'function') {
this.onRejectedCallbacks.push((reason) => {
try {
resolve(onRejected(reason));
} catch (error) {
reject(error);
}
});
} else {
this.onRejectedCallbacks.push(reject);
}
});
}
};
// Define the `catch` method
Promise.prototype.catch = function (onRejected) {
return this.then(null, onRejected);
};
// Define the `resolve` and `reject` functions
Promise.resolve = function (value) {
return new Promise((resolve) => resolve(value));
};
Promise.reject = function (reason) {
return new Promise((resolve, reject) => reject(reason));
};
// Define the `all` method
Promise.all = function (promises) {
return new Promise((resolve, reject) => {
const results = new Array(promises.length);
let completedPromises = 0;
promises.forEach((promise, index) => {
promise.then((value) => {
results[index] = value;
completedPromises++;
if (completedPromises === promises.length) {
resolve(results);
}
}).catch(reject);
});
});
};
// Define the `race` method
Promise.race = function (promises) {
return new Promise((resolve, reject) => {
promises.forEach((promise) => {
promise.then(resolve).catch(reject);
});
});
};
// Assign the polyfilled Promise object to the global scope
window.Promise = Promise;
}
// Usage
const myPromise = new Promise((resolve, reject) => {
setTimeout(() => {
resolve("Promise resolved!");
}, 1000);
});
myPromise.then((result) => {
console.log(result); // Output: Promise resolved!
});
function PromisePolyFill(executor) {
let onResolve, onReject;
let fulfilled = false,
rejected = false,
called = false,
value;
function resolve(v) {
fulfilled = true;
value = v;
if (typeof onResolve === "function") {
onResolve(value);
called = true;
}
}
function reject(reason) {
rejected = true;
value = reason;
if (typeof onReject === "function") {
onReject(value);
called = true;
}
}
this.then = function (callback) {
onResolve = callback;
if (fulfilled && !called) {
called = true;
onResolve(value);
}
return this;
};
this.catch = function (callback) {
onReject = callback;
if (rejected && !called) {
called = true;
onReject(value);
}
return this;
};
try {
executor(resolve, reject);
} catch (error) {
reject(error);
}
}
PromisePolyFill.resolve = (val) =>
new PromisePolyFill(function executor(resolve, _reject) {
resolve(val);
});
PromisePolyFill.reject = (reason) =>
new PromisePolyFill(function executor(resolve, reject) {
reject(reason);
});
let np = new PromisePolyFill((resolve, reject)=>{
setTimeout(()=>{
resolve(2)
}, 1000)
})
np.then((a)=>{
console.log(a)
})