1
function Stream() {
  let subscriber = new Map();

  return {
      subscribe: function(method) {
        if(typeof method === 'function') {
          subscriber.set(method);
        }
        else
          throw new Error('Pass a valid method.');
      },
      push: function(val) {
        [...subscriber].forEach(([method]) => method(val));
      },
      unsubscribe: function(method) {
        console.log(subscriber.has([method]));
        console.log([method]);
        [...subscriber].forEach(([method]) => console.log([method]));
        if (typeof method === 'function' && subscriber){
          subscriber.delete([method]);
        }
        [...subscriber].forEach(([method]) => console.log([method]));
      }
  };
}

var stream = new Stream();
stream.subscribe((val)=>console.log(val*1));
stream.subscribe((val)=>console.log(val*2));
stream.subscribe((val)=>console.log(val*3));

stream.push(2);
stream.push(3);
stream.unsubscribe((val)=>console.log(val*3));
stream.push(4);

In the unsubscibe function, which shows up that "subscriber.has([method]) " returns false to me, but after I print the method out and compare with in side of the subscriber map, which looks the same. Is there anything wrong here?

3
  • [method] creates a new array (with one element) each time, so it's never in the map. Commented Sep 26, 2019 at 19:01
  • You're missing the second argument to .set(). Commented Sep 26, 2019 at 19:02
  • 1
    stream.unsubscribe((val)=>console.log(val*3)) will never match anything anyway. Two arrow functions, even if equivalent logic, will never be the same. Commented Sep 26, 2019 at 19:07

1 Answer 1

1

You have two main problems.

First, the argument to .has() should just be method, not [method]. The keys subscribers are just functions, not arrays. All the places where you wrote [method] should not be in an array.

Second, you need to use named functions. Two functions with the same source code are not actually equal, so .has() won't be able to match them.

You should be using a Set rather than Map, since you're not associating any values with the functions. And there's no need to use [...subscriber], both Map and Set have forEach methods that iterate over the elements.

console.log(((val)=>console.log(val*3)) == ((val)=>console.log(val*3)))

will log false.

function Stream() {
  let subscriber = new Set();

  return {
      subscribe: function(method) {
        if(typeof method === 'function') {
          subscriber.add(method);
        }
        else
          throw new Error('Pass a valid method.');
      },
      push: function(val) {
        subscriber.forEach((method) => method(val));
      },
      unsubscribe: function(method) {
        console.log(subscriber.has(method));
        console.log(method);
        subscriber.forEach((method) => console.log(method));
        if (typeof method === 'function' && subscriber){
          subscriber.delete(method);
        }
        subscriber.forEach((method) => console.log(method));
      }
  };
}

var stream = new Stream();
const times1 = (val)=>console.log(val*1);
stream.subscribe(times1);
const times2 = (val)=>console.log(val*2);
stream.subscribe(times2);
const times3 = (val)=>console.log(val*3)
stream.subscribe(times3);

stream.push(2);
stream.push(3);
stream.unsubscribe(times3);
stream.push(4);

Sign up to request clarification or add additional context in comments.

2 Comments

I don't know, but it's in the MDN descriptions of both.
The compatibility charts for Map.prototype.forEach and Set.prototype.forEach both say it has been available since Chrome 38 and FF 25.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.