So I've been scratching this mental itch and was checking out how to handle change listeners to arrays without using Observables or external libraries.
The main idea is that I have a .json
file which is basically an array of objects (of type Rent
) and I'll use that file as my DB. I want to trigger a write to the file whenever the rentCollection
array is changed.
With the help of search engines and SO, I landed on this answer, and I've managed to implement something similar that seems to work as intended with a notable exception:
Given the following piece of code
const rentsFile = __dirname + "/data/rents.json";
export let rentCollection: Rent[] = [];
const populateRents = () => {
let rents = fs.readFileSync(rentsFile, { encoding: "utf8" });
rentCollection = JSON.parse(rents);
}
export const initDb = () => {
populateRents();
listenChangesinArray(rentCollection, writeFile);
}
/* @arr array you want to listen to
@callback function that will be called on any change inside array
*/
const listenChangesinArray = (arr: any, callback: any) => {
// Add more methods here if you want to listen to them
['pop', 'push', 'reverse', 'shift', 'unshift', 'splice', 'sort'].forEach((m: any) => {
arr[m] = (arg: any) => {
var res = Array.prototype[m].apply(arr, arg); // call normal behaviour
callback.apply(arr, arg); // finally call the callback supplied
return res;
}
});
}
const writeFile = (arg: any) => {
console.log("Write Arg: " + arg); // <== This argument is always undefined. Why???
try {
console.log(JSON.stringify(rentCollection, null, 2)); // <== I never see the new item in this collection. Why???
fs.writeFileSync(bloqsFile, JSON.stringify(rentCollection, null, 2), 'utf8');
console.log('Data successfully saved to disk');
} catch (error) {
console.log('An error has occurred ', error);
}
}
whenever I do a rentCollection.push(Rent)
, it will trigger the listenChangesinArray
method, and I can see/log the arg as being the passed Rent
object, and then call the writeFile
method too. However, when getting to writeFile
the argument is always undefined
. Why?? Is the way to handle the changes listener not right?
Appreciate any insight you can give. Thanks!
The second argument of apply
should be an array, but you pass it the argument that you provided to the array method, such as to push
, if any.
Fix this by getting all arguments in an array. So change this:
arr[m] = (arg: any) => {
to:
arr[m] = (...arg: any) => {
Now arg
will be an array, and so the second argument to both calls of apply
will have the correct type.