1.2.2 • Published 4 months ago

concurrentfetcher v1.2.2

Weekly downloads
-
License
MIT
Repository
github
Last release
4 months ago

ConcurrentFetcher

A javascript class for managing concurrent fetch requests.

The Fetch Web API is a neat tool for fetching/getting network resources in web applications. And although fetch() is generally easy to use, there are a few nuances in regards to error handling, asynchronous and concurrent processing, cancellation and so forth :-)

The ConcurrentFetcher class addresses the core challenges of concurrent requests, error handling, and cancellation.

Availability

Maintained at github : https://github.com/asicscreed/ConcurrentFetcher And published at npm: https://www.npmjs.com/package/concurrentfetcher

Install

npm install concurrentfetcher

Usage

Basically, you instantiate the class with an array of fetch requests and then call concurrentFetch(). For browsers it must be in an async context. It calls fetch and consumes the Response object. If a callback is defined, it is called for each response. Without a callback, the responses (data and errors, respectively) are collected and returned.

Browser example without callback (src="concurrentfetcher.iife.min.js"):

JavaScript: Example1

const requests = [{ url: "https://jsonplaceholder.typicode.com/photos/1" }, { url: "https://jsonplaceholder.typicode.com/comments/1" }];

const fetcher = new ConcurrentFetcher.ConcurrentFetcher(requests);
fetcher.concurrentFetch()
.then((data) => {
  const errors = data.errors ?? {};
  const results = data.results ?? {};
  if (errors.length > 0) document.write(JSON.stringify(errors));
  if (results.length > 0) document.write(JSON.stringify(results));
})

When data is returned without callback (as above), then data is a Promise<ConcurrentFetchResults> as this:

interface ConcurrentFetchResult {
  results: any[]; // json, text or blob data
  errors: { uniqueId: string; url: string | Request; error: FetchError }[];
}

The errors array is added with the unique Id, the request URL and a custom FetchError which sets error.status as response.status. The result array contains what is in the Response objects

Same currentFetch example, but with callback (src="concurrentfetcher.iife.min.js"):

JavaScript: Example2

const requests = [
  { url: "https://jsonplaceholder.typicode.com/photos/1",
    callback: (uniqueId, data, error, abortManager) => {
      if (error) document.write(JSON.stringify(error));
      else document.write(JSON.stringify(data));
    }
  },
  { url: "https://jsonplaceholder.typicode.com/comments/1",
    callback: (uniqueId, data, error, abortManager) => {
      if (error) document.write(JSON.stringify(error));
      else document.write(JSON.stringify(data));
    }
  }
];

const fetcher = new ConcurrentFetcher.ConcurrentFetcher(requests);
fetcher.concurrentFetch()
...

Hosted in Node.js with: concurrentfetcher.umd.min.js

JavaScript: Node.js

const people  = document.getElementById('people');
const fetcher = new ConcurrentFetcher.ConcurrentFetcher(requests);
fetcher.concurrentFetch()
.then((data) => {
  // you should handle if (data.errors.length > 0)
  if (data.results.length > 0) {
    people.innerHTML = data.results[0].map((person) => {
      return (
        '<div class="text-center mt-3">'+
          '<h5 class="mt-2 mb-0">'+person.name+'</h5>'+
          '<span>'+person.email+'</span>'+
          '<div class="px-4 mt-1">'+
            '<p class="fonts">'+person.company.catchPhrase+'</p>'+
          '</div>'+
        '</div>'
      );
    }).join('');
  } // data.results.length
})
.catch(error => console.error(error));  

Loaded in RequireJS with: concurrentfetcher.amd.min.js

JavaScript: RequireJS

requirejs.config({ paths: { ConcurrentFetcher: '/concurrentfetcher.amd.min' }});
requirejs(['ConcurrentFetcher'], function (ConcurrentFetcher) {
  const requests = [
      {
          url: 'https://api.github.com/users/asicscreed',
          headers: {
            Accept: "application/json",
            "Content-Type": "application/json",
          },
      }
  ];
  const fetcher = new ConcurrentFetcher.ConcurrentFetcher(requests);
  fetcher.concurrentFetch()
  .then(function (data) {
      if (data.results.length > 0) {
          user = data.results[0];
          document.getElementById('useravatar').src = user.avatar_url;
          document.getElementById('username').innerHTML = user.login;
      }
  })

Documentation:

Currently, all documentation is located in the docs folder. It is generated by JSDoc, and is therefore regular html documents.

Key points:

Concurrency: The class leverages Promise.all() for efficient concurrent execution and optimizing performance. Error handling: Custom error classes (FetchError, JsonParseError) and error reporting provide information for debugging and handling failures. Flexibility: The ability to configure individual fetch options and utilize both callbacks and promises makes the class adaptable to various use cases. Cancellation: The AbortManager class provides robust cancellation support, allowing for individual and global request cancellation. Support for client-controlled cancellation of a single request and of all requests. And timeout controlled cancellation on individual requests. Progress tracking: The optional progressCallback enables monitoring the progress of fetch requests. Retry logic: Retry mechanism for failed requests to improve the resilience of the class. Large data handling: Utilizes response.body to read large data in chunks.

Areas for consideration:

Advanced progress Tracking: Implement more granular progress tracking, such as byte transfer information for more detailed monitoring. Stream handling: Adding support for handling response streams, which would be beneficial for large data transfers. Testing: (More) Extensive unit and integration tests will greatly improve the classes reliability. Adaptability: Examples to demonstrate how to use the class in various environments (browser, Node.js, frontend frameworks, testing).


Get help: Post in our discussion board Review the GitHub status page

© 2023 GitHub Code of Conduct MIT License

1.2.0

4 months ago

1.1.0

4 months ago

1.2.2

4 months ago

1.2.1

4 months ago

1.0.3

4 months ago

1.0.2

4 months ago

1.0.1

4 months ago

1.0.0

4 months ago