简体   繁体   中英

What's the purpose of asynchronous generators in javascript?

I'm reading a book on Modern Asynchronous Javascript, and at one point the author writes some code to query a Github repo and retrieve all of its past commits.

The resulting array gives us 30 commits at a time, and the response header provides us with a link to the next page that contains additional results.

In the book, the author uses a generator function to accomplish this task like this:

    async function* generator(repo) {
      for (;;) {
        const response = await axios.get(repo, config);
        const data = response.data;
        for (let commit of data) {
          yield commit;
        }
        const link = response.headers.link;
        repo = /<(.*?)>; rel="next"/.exec(link)?.[1];
    
        if (repo === undefined) {
          // Breaking doesn't return anything, which means the iterator is done
          break;
        }
      }
    }

    async function getCommits(repo, maxData) {
      let i = 0;
      for await (const commit of generator(repo)) {
        console.log(`-------------repo: ${i}-----------------`);
        console.log(commit);
        if (i++ === maxData) {
          break;
        }
      }
    }

In trying to understand generator functions, I ended up rewriting this code how I would normally do it with a regular asynchronous function like this:

    async function getCommits(url, numItems) {
      let i = 0;
    
      while (i <= numItems) {
        let commits = await axios.get(url, config);
        let data = commits.data;
        let nextUrl = /<(.*?)>; rel="next"/.exec(commits.headers.link)?.[1];
        for (let commit of data) {
          if (i > numItems) break;
          console.log(`-------------repo: ${i}-----------------`);
          console.log(commit);
          i++;
        }
        url = nextUrl;
      }
    }

My code seems to work fine, and it seems to be shorter than the version using the generator function. I still don't fully understand the use-case for asynchronous generators or why I would ever use them.

Would love if someone could explain or point me towards some resources for learning more.

One of the purposes is to abstract the asynchronous actions. Say there's a library that has a function that does a number of asynchronous tasks. While it could instruct users of the library to perform the iterations themselves - such as with your second code - it's arguably nicer to provide users with an async generator instead.

If you implement the generator once , that generator can then be used wherever it's needed, instead of having to write imperative iterative code.

It's nicer to be able to say

// Here's how you use this library
for await (const result of getResults()) {
  console.log(result);
}

than

// Here's how you use this library
let i = 0;
const resultsGetter = makeAllResultsGetter();
while (i <= numItems) {
  const result = await resultsGetter();
  console.log(result);
  i++;
}

You definitely don't need to use async generators, but you may one time come across a situation where you find that the logic pattern they provide is the most elegant approach to the problem at hand.

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM