Tuesday, November 9, 2021

How to find the actual differences of 2 Objects in JS

 The title says it all, here is the solution I fall back to most of the times.

https://stackoverflow.com/a/8596559



var deepDiffMapper = function () {
return {
VALUE_CREATED: 'created',
VALUE_UPDATED: 'updated',
VALUE_DELETED: 'deleted',
VALUE_UNCHANGED: 'unchanged',
map: function(obj1, obj2) {
if (this.isFunction(obj1) || this.isFunction(obj2)) {
throw 'Invalid argument. Function given, object expected.';
}
if (this.isValue(obj1) || this.isValue(obj2)) {
return {
type: this.compareValues(obj1, obj2),
data: obj1 === undefined ? obj2 : obj1
};
}
var diff = {};
for (var key in obj1) {
if (this.isFunction(obj1[key])) {
continue;
}
var value2 = undefined;
if (obj2[key] !== undefined) {
value2 = obj2[key];
}
diff[key] = this.map(obj1[key], value2);
}
for (var key in obj2) {
if (this.isFunction(obj2[key]) || diff[key] !== undefined) {
continue;
}
diff[key] = this.map(undefined, obj2[key]);
}
return diff;
},
compareValues: function (value1, value2) {
if (value1 === value2) {
return this.VALUE_UNCHANGED;
}
if (this.isDate(value1) && this.isDate(value2) && value1.getTime() === value2.getTime()) {
return this.VALUE_UNCHANGED;
}
if (value1 === undefined) {
return this.VALUE_CREATED;
}
if (value2 === undefined) {
return this.VALUE_DELETED;
}
return this.VALUE_UPDATED;
},
isFunction: function (x) {
return Object.prototype.toString.call(x) === '[object Function]';
},
isArray: function (x) {
return Object.prototype.toString.call(x) === '[object Array]';
},
isDate: function (x) {
return Object.prototype.toString.call(x) === '[object Date]';
},
isObject: function (x) {
return Object.prototype.toString.call(x) === '[object Object]';
},
isValue: function (x) {
return !this.isObject(x) && !this.isArray(x);
}
}
}();
view raw deepdiff.ts hosted with ❤ by GitHub

Wednesday, April 21, 2021

Why do we need Monads?

  1. We want to program only using functions. (“functional programming” after all -FP).

  2. Then, we have a first big problem. This is a program:

    f(x) = 2 * x

    g(x,y) = x / y

How can we say what is to be executed first? How can we form an ordered sequence of functions (i.e. a program) using no more than functions?

Solution: compose functions. If you want first g and then f, just write f(g(x,y)). OK, but …

  1. More problems: some functions might fail (i.e. g(2,0), divide by 0). We have no “exceptions” in FP. How do we solve it?

Solution: Let’s allow functions to return two kind of things: instead of having g : Real,Real -> Real (function from two reals into a real), let’s allow g : Real,Real -> Real | Nothing (function from two reals into (real or nothing)).

  1. But functions should (to be simpler) return only one thing.

Solution: let’s create a new type of data to be returned, a “boxing type” that encloses maybe a real or be simply nothing. Hence, we can have g : Real,Real -> Maybe Real. OK, but …

  1. What happens now to f(g(x,y))? f is not ready to consume a Maybe Real. And, we don’t want to change every function we could connect with g to consume a Maybe Real.

Solution: let’s have a special function to “connect”/“compose”/“link” functions. That way, we can, behind the scenes, adapt the output of one function to feed the following one.

In our case: g >>= f (connect/compose g to f). We want >>= to get g's output, inspect it and, in case it is Nothing just don’t call f and return Nothing; or on the contrary, extract the boxed Real and feed f with it. (This algorithm is just the implementation of >>= for the Maybe type).

  1. Many other problems arise which can be solved using this same pattern: 1. Use a “box” to codify/store different meanings/values, and have functions like g that return those “boxed values”. 2. Have composers/linkers g >>= f to help connecting g's output to f's input, so we don’t have to change f at all.

  2. Remarkable problems that can be solved using this technique are:

    • having a global state that every function in the sequence of functions (“the program”) can share: solution StateMonad.

    • We don’t like “impure functions”: functions that yield different output for same input. Therefore, let’s mark those functions, making them to return a tagged/boxed value: IO monad.

PS: this answer can be found on SO at this link: https://stackoverflow.com/a/28135478 

Friday, April 16, 2021

Do you need to wrap RXJS Observables in try-catch?

 No.

Internally errors are caught implicitly.

Here is a good example, give it a swing yourself! (Source)


import { throwError, of, Observable } from 'rxjs';
import { catchError, map } from 'rxjs/operators';
const exampleOne$ = new Observable(subscriber => {
throw new Error('thrown');
});
exampleOne$.pipe(
catchError(val => of(`Exmaple One ${val}`))
).subscribe(console.log); // Exmaple One Error: thrown
const exampleTwo$ = new Observable(subscriber => {
try {
throw new Error('native error')
}
catch (e) {
subscriber.error(e);
}
});
exampleTwo$.pipe(
catchError(val => of(`Example Two ${val}`))
).subscribe(console.log); // Example Two Error: thrown

Saturday, April 10, 2021

Conditional Promise.all

Have been in a situation where you needed to dynamically shoot out HTTP requests based on some branching logic? Are you using a Promise based HTTP client library like fetch or axios?

Fear not, here is a solution for your needs!

In general the solution is based on coming up with an interface that's not only returning the data when the Promise was resolved, but also give a companion flag that identifies the promise it was initiated from.


interface DynamicPromiseResult {
data: unknown;
promise: string;
}
const promises: Array<Promise<DynamicPromiseResult>> = []
if (true) { // some logic
const promise1 = fetch('https://jsonplaceholder.typicode.com/posts/1').then(data => ({ data, promise: 'promise1' }));
promises.push(promise1);
}
if (false) { // some logic
const promise2 = fetch('https://jsonplaceholder.typicode.com/posts/2').then(data => ({ data, promise: 'promise2' }));
promises.push(promise2);
}
const results = await Promise.all(promises)
results.forEach(result => {
// pattern matching would be lovely here, but JS/TS does not support it yet
switch (result.promise) {
case 'promise1':
doSomething();
break;
case 'promise2':
doSomething2();
break;
default:
throw new Error('Resulting promise not found');
}
});

You can find the idea on this SO post as well.