I'm trying to wrap a list of functions over a callback function. Each of the function in the list takes in the value of the callback and returns a modified value. When I try to do this in a straight forward way, it does recursion, and the stack eventually runs out of space, and throws an error.
I tried solving the problem by using a wrapper function that took in a function, wrapped it with another one, and then returned it, and that solved the problem.
Look at the subscribe
function:
class Observable {
constructor() {
this._subscribers = [];
this._operators = [];
}
next(val) {
this._subscribers.forEach(subscriber => {
subscriber(val);
});
}
subscribe(callback) {
if (this._operators.length > 0) {
let ogCallback;
this._operators.forEach((operator, index) => {
ogCallback = callback;
/** ==== call stack full error =====
* callback = (val) => {
* ogCallback(operator(val));
* };
*/
// This works
callback = ((func) => {
const wrapper = (val) => {
func(operator(val));
};
return wrapper;
})(ogCallback);
});
this._operators = [];
}
this._subscribers.push(callback);
}
pipe(operator) {
this._operators.unshift(operator);
return this;
}
}
const observable = new Observable();
observable.pipe(val => val + 2).pipe(val => val * 2).subscribe(val => console.log(val));
observable.next(5);
Why does this happen? They both seem to be the same thing.
I suspect it's from the series of closures created by:
ogCallback = callback;
callback = (val) => {
ogCallback(_function(val));
}
ogCallback and callback are global. After the initial iteration, callback has the value:
(val) => ogCallback(_function(val))
ogCallback has a closure to the global ogCallback , so it's value is whatever it was given from the last iteration, as does callback , potentially causing circular references.
The second example breaks the closure by creating a local variable func in the assigned function expression that is passed the value of ogCallback using an immediately invoked function expression (IIFE).
_functions.forEach((_function, index) => {
ogCallback = callback;
callback = ((func) => {
const wrapper = (val) => {
func(_function(val));
};
return wrapper;
})(ogCallback);
});
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.