Skip to content

Instantly share code, notes, and snippets.

@Elergy
Last active October 18, 2019 11:01
Show Gist options
  • Save Elergy/ea8b6b4d16339c0dec90f8befc24c88d to your computer and use it in GitHub Desktop.
Save Elergy/ea8b6b4d16339c0dec90f8befc24c88d to your computer and use it in GitHub Desktop.

Process

  1. Step 1: ask people a question without explanation
  2. Step 2: give them documentation covering this piece and ask again
  3. Step 3: ask them whether it generally makes sense for them. Why not?

Example of the process

What this code would log?

$.each(['a', 'b'], (first, second) => console.log(first, second));

Options:

  1. 'a' \n 'b'

  2. 'a', 0 \n 'b', 1

  3. 0, 'a' \n 1, 'b'

  4. Step one without explanation: I'd say "2"

  5. Step two with documentation: I'd change it to "3", because https://api.jquery.com/jQuery.each/ explains it pretty well

  6. Step three: I'd say that it doesn't make much sense for me because I'd rather have it consistent with Array.prototype.each

Questions

It's natural to emit values from outside

const emitter = new Emitter();

emitter.each(value => console.log(value));

emitter.next('foo');
emitter.next('bar');

Options:

  1. 'foo', 'bar'
  2. Nothing
  3. Error

It's not natural to subscribe after we emitted

const emitter = new Emitter();

emitter.next('foo');
emitter.next('bar');

emitter.each(value => console.log(value));

Options:

  1. 'foo', 'bar'
  2. Nothing
  3. Error

It's natural to emit values from inside and having to call run explicitly

const emitter = new Emitter({
  run(me){
    me.send('foo')
    me.send('bar')
  }
});

emitter.each(value => console.log(value));
emitter.run();

Options:

  1. 'foo'
  2. 'bar'
  3. 'foo', 'bar'
  4. Nothing

It's natural to emit values asynchronously from inside

const emitter = new Emitter({
  run(me){
    me.send('foo')
    setTimeout(() => me.send('bar'), 100);
  }
});

emitter.each(value => console.log(value));
emitter.run();

Options:

  1. 'foo'
  2. 'bar'
  3. 'foo', 'bar'
  4. Nothing

It's natural to have several subscribers

const emitter = new Emitter();

emitter.each(value => console.log("first", value));
emitter.each(value => console.log("second", value));

emitter.next('foo');
emitter.next('bar');

Options:

  1. "first, foo" / "second, foo" / "first, bar" / "second, bar"
  2. "first, foo" / "first, bar" / "second, foo" / "second, bar"
  3. "first, foo" / "first, bar"
  4. "second, foo" / "second, bar"
  5. Error

It's natural to add several subscriptions at different time

const emitter = new Emitter();

emitter.each(value => console.log("first", value));
emitter.next('foo');

emitter.each(value => console.log("second", value));
emitter.next('bar');

Options:

  1. "first, foo" / "second, foo" / "first, bar" / "second, bar"
  2. "first, foo" / "first, bar" / "second, bar"
  3. Error

It's natural to expect that previous subscribers can change mutable values

const emitter = new Emitter();

emitter.each(object => {
  console.log(object.value);
  object.value = 'baz';
});
emitter.each(object => console.log(object.value));

emitter.next({ value: 'foo'});

Options:

  1. "foo", "baz"
  2. "foo", "bar"
  3. Error

It's natural to use a static function run to run an emitter

run(['foo', 'bar'], value => console.log(value));

Options:

  1. "foo", "bar"
  2. Nothing
  3. Error

It's natural to expect that run doesn't return an emitter

run(['foo', 'bar']).each(value => console.log(value))

Options:

  1. "foo", "bar"
  2. Nothing
  3. Error

It's natural to do simple manipulations on the values using simple operators, such as map

const emitter = new Emitter();
emitter.each(
  map(value => value * 2),
  value => console.log(value)
);
emitter.next(1);
emitter.next(2);

Options:

  1. 1, 2
  2. 2, 4
  3. 2
  4. 4
  5. Error

It's natural to use asynchronous functions with operators

const emitter = new Emitter();
emitter.each(
  map(async (value) => {
    const temp = await new Promise((resolve) => {
      setTimeout(() => resolve(value * 10), 1000);
    });
    return temp + 1;
  }),
  value => console.log(value)
);
emitter.next(1);
emitter.next(2);

Options:

  1. Promise, Promise
  2. 11, 21
  3. NaN, Nan
  4. Error

It's natural for promises to unwrap automatically inside emitters

const emitter = new Emitter();
emitter.each(
  map((value) => {
    return new Promise(resolve => resolve(value))
  }),
  value => console.log(value)
);
emitter.next(1);
emitter.next(2);

Options:

  1. Promise, Promise
  2. 1, 2
  3. Error

It is not natural to call operators as methods of an emitter

const emitter = new Emitter();
emitter
  .map(value => value * 2)
  .each(value => console.log(value))

emitter.next(1);
emitter.next(2);

Options:

  1. 1, 2
  2. 2, 4
  3. 2
  4. 4
  5. Error

It's natural to combine these operators together

const emitter = new Emitter();
emitter.each(
  filter(value => value > 2),
  map(value => value * 2),
  value => console.log(value)
);
emitter.next(1);
emitter.next(2);
emitter.next(3);
emitter.next(4);

Options:

  1. 6, 8
  2. Error

It's natural to use run to simplify this code

run(
  [1, 2, 3, 4],
  filter(value => value > 2),
  map(value => value * 2),
  value => same(value, expected.shift())
);

Options:

  1. 6, 8
  2. Error

It's still not natural to call methods on .run

run(
  [1, 2, 3, 4]
).filter(value => value > 2)
 .map(value => value * 2)
 .each(value => console.log(value));

Options:

  1. 6, 8
  2. Error

It's natural to use limit for concurrency management

run(
  [1, 2, 3, 4, 5, 6],
  limit(2),
  map(async (value) => {
    return await new Promise(resolve => setTimeout(() => resolve(value * 10), 500));
  }),
  value => console.log(value)
);

Options:

  1. 1, 2
  2. 10, 20
  3. 10, 20, 30, 40, 50, 60
  4. Error
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment