title: How to write an async counter, i.e. a counter with sync interface for async code, using only the native Promise?
body: <p>I want to create an object that exposes the following interface:</p>
  
  <pre><code>// Create the object that counts to three
  const c = counter(3);
  // c.finished is a promise that resolves when c.count() is invoked three times
  c.finished.then(() =&gt; console.log('counted three times!'));
  
  // Somewhere else, c.count() is invoked in async body
  setTimeout(() =&gt; c.count(), 500);
  setTimeout(() =&gt; c.count(), 1000);
  setTimeout(() =&gt; c.count(), 1500);
  </code></pre>
  
  <p>I expect that <code>c.finished</code> resolves after 1.5 seconds.</p>
  
  <p>How to write <code>counter(countTimes)</code> using only the native <code>Promise</code> API?</p>
  
  <p><strong>Disclosure</strong> I already have <a href="https://github.com/assister-ai/async-counter/blob/master/index.js" rel="nofollow noreferrer">a solution</a> to the above problem, want to know what is the most elegant way to do it. </p>
  
  <p><strong>Edit</strong></p>
  
  <p>My original solution was:</p>
  
  <pre><code>class AsyncCounter {
    constructor(countTimes) {
      let currentCount = 0;
      this.countTimes = countTimes;
      this.ready = new Promise(resolveReady =&gt; {
        this.finished = new Promise(resolveFinished =&gt; {
          const count = () =&gt; {
            currentCount++;
            if (currentCount &gt;= this.countTimes) {
              resolveFinished();
            }
            return currentCount;
          };
          this.count = () =&gt; this.ready.then(() =&gt; count());
          resolveReady();
        });
      });
    }
  }
  
  const counter = countTimes =&gt; new AsyncCounter(countTimes);
  </code></pre>
  
  <p>As suggested by @Bergi and according to <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise#Parameters" rel="nofollow noreferrer">MDN docs for executor function</a>:</p>
  
  <blockquote>
    <p>the executor is called before the Promise constructor even returns the
    created object</p>
  </blockquote>
  
  <p>Hence, the <code>ready</code> promise in the above solution is not necessary. </p>