Skip to content

Instantly share code, notes, and snippets.

@sachinKumarGautam
Last active February 24, 2023 09:02
Show Gist options
  • Save sachinKumarGautam/b5b2a73fc95fc10178763a9d4a202abb to your computer and use it in GitHub Desktop.
Save sachinKumarGautam/b5b2a73fc95fc10178763a9d4a202abb to your computer and use it in GitHub Desktop.
This doc includes polyfills for the most common JS functions
// debounce
function debounce(func, wait, immediate) {
var timeout;
return function() {
var context = this, args = arguments;
var later = function() {
timeout = null;
if (!immediate) func.apply(context, args);
};
var callNow = immediate && !timeout;
clearTimeout(timeout);
timeout = setTimeout(later, wait);
if (callNow) func.apply(context, args);
};
};
// throttle
function throttle(func, wait) {
// your code here
let timer = null;
let lastArgs = null;
return function(...args) {
if(timer) {
lastArgs = args;
} else {
func.apply(this, args);
timer = setTimeout(()=>{
if(lastArgs) {
func.apply(this,lastArgs);
timer = null;
}
}, wait)
}
}
}
// Array map
/**
* Map function is attached to the array prototype
* It takes in a callback and passes every item in the array
* through the callback, the result is pushed into a new array
* which is returned
*/
/**
* The callback gets 3 arguments
* the item, the index and the execution context
*/
Array.prototype.newMap = function (callback) {
const result = [];
for (let index = 0; index < this.length; index++) {
// This is primarily to check if the item
// exists in the array,
if (this.indexOf(this[index]) > -1) {
result[index] = callback(this[index], index, this)
}
}
return result
}
// Array Filter
/**
* Filter function is attached to the array prototype
* It takes in 3 parameters, callback and a context (this)
* argument, the callback is invoked with the current item
* the index, the array,
*/
/**
* The callback gets 3 arguments
* the item, the index and the execution context
*/
Array.prototype.newFilter = function (callback, context) {
const result = [];
for (let index = 0; index < this.length; index++) {
if (callback.call(context, this[index], index, this)) {
result.push(this[index])
}
}
return result
}
//Array Reduce
/**
* Reduce function is attached to the array prototype
* It takes in a callback and passes every item, along with accumulator in the array
* through the callback, and also a starting value
*/
/**
* The callback gets 4 arguments
* an accumulator, current value, index, current array
*
*/
Array.prototype.newReduce = function (callback, startingValue) {
// as starting value is an optional param
// make a check
let accumulator = startingValue || undefined;
for (let index = 0; index < this.length; index++) {
if (accumulator) {
accumulator = callback.call(accumulator, accumulator, this[index], index, this)
} else {
accumulator = this[index]
}
}
return accumulator;
}
//Array forEach
/**
* Foreach function is attached to the array prototype
* It takes in a callback and passes every item in the array
* through the callback
*/
/**
* The callback gets 3 arguments
* the item, the index and the execution context
* A for each array loop cannot be broken using break;
*/
Array.prototype.newForEach = function (callback, context) {
for (let index = 0; index < this.length; index++) {
// This is primarily to check if the item
// exists in the array,
if (this.indexOf(this[index]) > -1) {
callback.call(context, this[index], index, this)
}
}
}
//Bind
Function.prototype.newBind = function (context) {
const currentContext = this;
const currentArguments = Array.prototype.slice.call(arguments, 1); // Dont need the context
return function () {
const args = Array.prototype.slice.call(arguments);
currentContext.apply(context, currentArguments.concat(args))
}
// Async Parallel fucntion
// Run the tasks collection of functions in parallel, without waiting until the previous function has completed. If any of the functions pass an error to its callback, the main callback is immediately called with the value of the error.
// Question
// You have an asyncFunction which takes a callback and the result of the asyncFunction is passed to the callback, create a function asyncParallel which takes an array of asyncFunctions and a resultCallback. When the asyncActions are completed the resultCallback must be invoked with the values.
function asyncParallel(taskList, resultsCallback) {
const results = [];
let tasksCompleted = 0;
taskList.forEach(asyncTask => {
asyncTask(value => {
results.push(value);
tasksCompleted++;
if (tasksCompleted >= taskList.length) {
resultsCallback.call(null, results);
}
});
});
}
const taskList = [
createAsyncTask(),
createAsyncTask(),
createAsyncTask(),
createAsyncTask(),
createAsyncTask(),
createAsyncTask()
];
asyncParallel(taskList, result => {
console.log('got the results', result);
});
// async series
// Run the functions in the tasks collection in series, each one running once the previous function has completed. If any functions in the series pass an error to its callback, no more functions are run, and callback is immediately called with the value of the erro
// Question
// You have an asyncFunction which takes a callback and the result of the asyncFunction is passed to the callback, create a function asyncSeries which takes an array of asyncFunctions and a resultCallback. asyncSeries should sequentially execute the asyncActions, on completion of the last task, the resultCallback should be invoked with the results in an array.
function asyncSeries(taskList, callback) {
var arr = [];
let tasksCompleted = 0;
taskList.reduce((accum, current) => {
return accum.then(someVal => {
return new Promise((resolve, reject) => {
current((value) => {
arr.push(value)
tasksCompleted++
if (tasksCompleted === taskList.length) {
callback.call(null, arr)
} else {
resolve(value)
}
})
})
})
}, Promise.resolve())
}
const taskList = [
createAsyncTask(),
createAsyncTask(),
createAsyncTask(),
createAsyncTask(),
createAsyncTask(),
]
asyncSeries(taskList, (result) => {
console.log("got the results", result)
})
// Memoize
function memoize(fn) {
const cache = {}
return function() {
const args = JSON.stringify(arguments);
if (cache[args]) {
return cache[args]
}
const evaluatedValue = fn.apply(this, arguments);
cache[args] = evaluatedValue;
return evaluatedValue;
}
}
function factorial(n) {
if(n === 0 || n === 1) {
return 1
}
return factorial(n-1) * n;
}
const memoizedFactorial = memoize(factorial)
memoizedFactorial(1000) // slow
memoizedFactorial(1000) // faster
//Implement Promise.all
function task(time) {
return new Promise(function (resolve, reject) {
setTimeout(function () {
resolve(time);
}, time);
});
}
const taskList = [task(1000), task(5000), task(3000)];
// returns promise with results in an array
function myPromiseAll(taskList) {
const results = []
let promisesCompleted = 0;
return new Promise((resolve, reject) => {
taskList.forEach((promise, index) => {
promise.then((val) => {
results[index] = val;
promisesCompleted += 1;
if (promisesCompleted === taskList.length) {
resolve(results)
}
})
.catch(error => {
reject(error)
})
})
});
}
myPromiseAll(taskList)
.then(results => {
console.log("got results", results)
})
.catch(console.error)
//Promise.allSettled polyfill
function promiseAllSettled(promiseArray) {
let fullfilledPromisesCount = 0
let result = []
return new Promise((resolve, reject) => {
promiseArray.forEach((promiseItem, index) => {
console.log('promiseItem before', promiseItem.isFullfilled)
promiseItem.then((response) => {
console.log('promiseItem after', promiseItem)
result[index] = {status: 'resolved', value: response}
console.log()
fullfilledPromisesCount += 1;
if(fullfilledPromisesCount === promiseArray.length) {
resolve(result)
}
}, (error) => {
fullfilledPromisesCount += 1;
result[index] = {status: 'rejected', error: error}
if(fullfilledPromisesCount === promiseArray.length) {
resolve(result)
}
})
})
})
}
const taskList = [task(1000), task(2000), task(1)]
console.log(promiseAllSettled(taskList).then((allTasks) => {
console.log('allTasks', allTasks)
}).catch((error) => {
console.log('dkdlkl', error)
}))
//Flatten the array
Array.prototype.flatten = function () {
let flatArray = []
for (let index = 0; index < this.length; index++) {
const element = this[index];
if (Array.isArray(element)) {
flatArray = flatArray.concat(this.flatten.call(element))
} else {
flatArray.push(element)
}
}
return flatArray;
}
// function flatten
//const nestedArr = [[1], [[1, 4, [5, 3]], [1, 2, 3, 4]]] => [1, 1, 4, 5, 3, 1, 2, 3, 4]
const nestedArr = [[1], [[1, 4, [5, 3]], [1, 2, 3, [3, 4, [2, [22, [3, 4, 5, 6, 5, [2]]]]], 4]]]
//const nestedArr = [1, 2, 3, 4, [1]]
const flat = nestedArr.flatten();
console.log(flat);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment