Modify wrapper function for a function with parameter - javascript

I have a wrapper function as
const wrap = (func) =>{
return () => {
try {
return func();
} catch (e) {
console.log(e.message);
return null;
}
};
}
how should i modify my wrapper function(wrap) to handle both the function call i.e one with param and other without param

Simply pass args to your wrapped function and accept them in the wrapper one:
const wrap = (func) =>{
return (...args) => {
try {
return func(...args);
} catch (e) {
console.log(e.message);
return null;
}
};
}
PS: Peach is not gross.

Related

Javascript Promisification, why use "call"?

I want to understand why in the below example, the "call" method was used.
loadScript is a function that appends a script tag to a document, and has an optional callback function.
promisify returns a wrapper function that in turn returns a promise, effectively converting `loadScript' from a callback-based function to a promise based function.
function promisify(f) {
return function (...args) { // return a wrapper-function
return new Promise((resolve, reject) => {
function callback(err, result) { // our custom callback for f
if (err) {
reject(err);
} else {
resolve(result);
}
}
args.push(callback); // append our custom callback to the end of f arguments
f.call(this, ...args); // call the original function
});
};
}
// usage:
let loadScriptPromise = promisify(loadScript);
loadScriptPromise(...).then(...);
loadScript():
function loadScript(src, callback) {
let script = document.createElement("script");
script.src = src;
script.onload = () => callback(null, script);
script.onerror = () => callback(new Error(`Script load error for ${src}`));
document.head.append(script);
}
I understand that call is used to force a certain context during function call, but why not use just use f(...args) instead of f.call(this, ...args)?
promisify is a general-purpose function. Granted, you don't care about this in loadScript, but you would if you were using promisify on a method. So this works:
function promisify(f) {
return function (...args) { // return a wrapper-function
return new Promise((resolve, reject) => {
function callback(err, result) { // our custom callback for f
if (err) {
reject(err);
} else {
resolve(result);
}
}
args.push(callback); // append our custom callback to the end of f arguments
f.call(this, ...args); // call the original function
});
};
}
class Example {
constructor(a) {
this.a = a;
}
method(b, callback) {
const result = this.a + b;
setTimeout(() => callback(null, result), 100);
}
}
(async () => {
try {
const e = new Example(40);
const promisifiedMethod = promisify(e.method);
const result = await promisifiedMethod.call(e, 2);
console.log(result);
} catch (error) {
console.error(error);
}
})();
That wouldn't work if promisify didn't use the this that the function it returns receives:
function promisifyNoCall(f) {
return function (...args) { // return a wrapper-function
return new Promise((resolve, reject) => {
function callback(err, result) { // our custom callback for f
if (err) {
reject(err);
} else {
resolve(result);
}
}
args.push(callback); // append our custom callback to the end of f arguments
f(...args); // call the original function *** changed
});
};
}
class Example {
constructor(a) {
this.a = a;
}
method(b, callback) {
const result = this.a + b;
setTimeout(() => callback(null, result), 100);
}
}
(async () => {
try {
const e = new Example(40);
const promisifiedMethod = promisifyNoCall(e.method);
const result = await promisifiedMethod.call(e, 2);
console.log(result);
} catch (error) {
console.error(error);
}
})();

How to implement a simpler Promise in JavaScript?

I'm learning JavaScript, and I decided that an excelent chalenge would be to implement a custom Promise class in JavaScript. I managed to implement the method then, and it works just fine, but I'm having difficulties with the error handling and the method catch. Here is my code for the Promise class (in a module called Promise.mjs):
export default class _Promise {
constructor(executor) {
if (executor && executor instanceof Function) {
try {
executor(this.resolve.bind(this), this.reject.bind(this));
} catch (error) {
this.reject(error);
}
}
}
resolve() {
if (this.callback && this.callback instanceof Function) {
return this.callback(...arguments);
}
}
reject(error) {
if (this.errorCallback && this.errorCallback instanceof Function) {
return this.errorCallback(error);
} else {
throw `Unhandled Promise Rejection\n\tError: ${error}`;
}
}
then(callback) {
this.callback = callback;
return this;
}
catch(errorCallback) {
this.errorCallback = errorCallback;
return this;
}
}
When I import and use this class in the following code, all the then() clauses run as according, and I get the desired result in the console:
import _Promise from "./Promise.mjs";
function sum(...args) {
let total = 0;
return new _Promise(function (resolve, reject) {
setTimeout(function () {
for (const arg of args) {
if (typeof arg !== 'number') {
reject(`Invalid argument: ${arg}`);
}
total += arg;
}
resolve(total);
}, 500);
});
}
console.time('codeExecution');
sum(1, 3, 5).then(function (a) {
console.log(a);
return sum(2, 4).then(function (b) {
console.log(b);
return sum(a, b).then(function (result) {
console.log(result);
console.timeEnd('codeExecution');
});
});
}).catch(function (error) {
console.log(error);
});
But, when I add an invalid argument to the sum() function, i.e. not a number, the reject() method runs, but it don't stop the then() chain, as should be, and we also get an exception. This can be seen from the following code:
import _Promise from "./Promise.mjs";
function sum(...args) {
let total = 0;
return new _Promise(function (resolve, reject) {
setTimeout(function () {
for (const arg of args) {
if (typeof arg !== 'number') {
reject(`Invalid argument: ${arg}`);
}
total += arg;
}
resolve(total);
}, 500);
});
}
console.time('codeExecution');
sum(1, 3, '5').then(function (a) {
console.log(a);
return sum(2, 4).then(function (b) {
console.log(b);
return sum(a, b).then(function (result) {
console.log(result);
console.timeEnd('codeExecution');
});
});
}).catch(function (error) {
console.log(error);
});
Also, if I catch an error in nested then() methods, the outer catch() doesn't notice this and I get an exception again. The goal is to implement a lightweight functional version of Promises, but not necessarily with all its functionality. Could you help me?
The problem in your code is that your sum function calls both the reject and the resolve functions. There's no handling in the sum function that will cause it not to call the resolve function at the end, and there is nothing in your _Promise that blocks this behavior.
You have 2 options to fix this.
Option 1 would be if you want your _Promise to act like a real Promise you will need to manage a state and once a promise got to a final state stop calling the callback or errorCallback.
Option 2 would be to prevent from calling both reject and resolve in the function calling the _Promise, in this case, the sum function.
With the comments that you guys provide me, I was able to improve the code and correct the errors mentioned, as shown below. Now, I would like you to give me suggestions on how to proceed and improve the code. Thanks. (The code can also be found on github).
const PENDING = 0;
const FULFILLED = 1;
const REJECTED = 2;
function _Promise(executor) {
let state = PENDING;
let callOnFulfilled = [];
let callOnRejected = undefined;;
function resolve(...args) {
if (!state) {
state = FULFILLED;
}
resolveCallbacks(...args);
};
function reject(error) {
state = REJECTED;
if (callOnRejected && (callOnRejected instanceof Function)) {
callOnRejected(error);
callOnRejected = undefined;
callOnFulfilled = [];
} else {
throw `Unhandled Promise Rejection\n\tError: ${error}`;
}
};
function resolveCallbacks(...value) {
if (state !== REJECTED) {
let callback = undefined;
do {
callback = callOnFulfilled.shift();
if (callback && (callback instanceof Function)) {
const result = callback(...value);
if (result instanceof _Promise) {
result.then(resolveCallbacks, reject);
return;
} else {
value = [result];
}
}
} while (callback);
}
};
if (executor && (executor instanceof Function)) {
executor(resolve, reject);
}
this.then = function (onFulfilled, onRejected) {
if (onFulfilled) {
callOnFulfilled.push(onFulfilled);
if (state === FULFILLED) {
resolveCallbacks();
}
}
if (onRejected && !callOnRejected) {
callOnRejected = onRejected;
}
return this;
};
this.catch = function (onRejected) {
return this.then(undefined, onRejected);
};
}
function sum(...args) {
let total = 0;
return new _Promise(function (resolve, reject) {
setTimeout(function () {
for (const arg of args) {
if (typeof arg !== 'number') {
reject(`Invalid argument: ${arg}`);
}
total += arg;
}
resolve(total);
}, 500);
});
}
console.time('codeExecution');
sum(1, 3, 5).then(function (a) {
console.log(a);
return sum(2, 4).then(function (b) {
console.log(b);
return sum(a, b).then(function (result) {
console.log(result);
return 25;
});
}).then(function (value) {
console.log(value);
console.timeEnd('codeExecution');
});
}).catch(function (error) {
console.log(error);
});

How to alter result of callback/promise function?

I have a function that can return result in both callback and promise:
function foo(args, cb) {
// do stuff
const promise = getSomePromise();
if (cb) {
promise.then((result) => {
cb(null, result);
}, (err) => {
cb(err);
});
} else {
return promise;
}
}
I want to alter the result of promise before returning it. How to do this in a way that introduces the least amount of spaghetti code?
Add a function to alter and return modified result
function alterResult(result){
const alteredResult = /// do something to result
return alteredResult;
}
Then add it in a then()to:
const promise = getSomePromise().then(alterResult);
You can write a function which returns something and pass it to the callback when initiating it like this
function foo(cb) {
const promise = getSomePromise(); // return some promise
promise.then((result) => { // result is here just "Hello"
cb(doSomething(result)); // return the altered value here to the callback
})
}
function getSomePromise() {
return new Promise((resolve, _) => resolve("Hello")) // make a new promise
}
function doSomething(res) { // define a function that alters your result
return res + ", World"
}
foo((val) => console.log(val)) // log it

decorators: "this" is undefined when accessed in descriptor.value

I am trying out decorators, I have written a decorator that basically returns a new function that does some `console.log.
This is what my decorator looks like:
function test(target, name, descriptor) {
const original = descriptor.value;
console.log("bbau");
if (typeof original === 'function') {
descriptor.value = function (...args) {
console.log(`Arguments: ${args}`);
try {
console.log("executing");
const result = original.apply(this, args);
console.log("done");
console.log(`Result: ${result}`);
return result;
} catch (e) {
console.log(`Error: ${e}`);
throw e;
}
}
}
return descriptor;
}
And this is how I am using it:
class TestController extends BaseController<//..> {
// ...
#test
testIt(req: Request, res: Response) : Response {
this.sendResponse();
}
sendResponse(options: ISendResponseOptions, res: Response) : Response {
// return response
}
}
``
However, when executed an error is raised: Error: TypeError: Cannot read property 'sendResponse' of undefined.
Any thoughts about what it could be? Thanks!
You should generally use an arrow function when you want to capture this from the context you declared the function in (or when this does not matter). In this case you really want this to be the object the function was called on so you should use a regular function :
const test = (target, name, descriptor) => {
const original = descriptor.value;
if (typeof original === 'function') {
descriptor.value = function (...args) {
console.log(`Arguments: ${args}`);
try {
console.log("executing");
const result = original.apply(this, args);
console.log("done");
console.log(`Result: ${result}`);
return result;
} catch (e) {
console.log(`Error: ${e}`);
throw e;
}
}
}
return descriptor;
}
You can test it out in the playground
If you use this function as a parameter to another function you should also call bind to set this for the function (otherwise the caller will determine the value of this):
router.route("/").post(testController.testIt.bind(testController))

How to make a nested function call within an IIFE?

const parkReport = () => {
return {
averageAge: () => {
return console.log('Something');
}
}
};
const initialize = ( parkReport => {
return parkReport.averageAge();
})(parkReport);
In the IIFE initialize parkReport.averageAge() is showing an error of not a function. How do you call the nested AverageAge() from initialize?
You need to call the parkReport function. Here you are passing parkReport as a callback to the IIFE. so you need to call it to expect something returned from it.
const parkReport = () => {
return {
averageAge: () => {
return console.log('Something');
}
}
};
const initialize = (parkReport => {
return parkReport() // call it
.averageAge(); // and get the age
})(parkReport);

Categories

Resources