npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

redux-fetch-api

v1.0.2

Published

Isomorphic fetch api for use with redux-apis

Downloads

19

Readme

version license installs build mind BLOWN

redux-fetch-api v1.0.2

Isomorphic fetch api for use with redux-apis

Installation

npm install --save redux-fetch-api

NOTE When using redux-fetch-api on older versions of Node, or older browsers that don't support Promises, make sure to install a Promise polyfill as well. This library is tested on Node JS 0.10, as can be seen in the .travis.yml config file, using babel-polyfill.

Dependencies and imports

redux-fetch-api does not depend on, but is designed to work well with redux-apis.

import { remote, endpoint, fetcher } from 'redux-fetch-api';

Or, using ES5 / require:

var remote = require('redux-fetch-api').remote;
var endpoint = require('redux-fetch-api').endpoint;
var fetcher = require('redux-fetch-api').fetcher;

NOTE: redux-fetch-api depends on a global function fetch being available, as specified by the whatwg fetch specification.

For NodeJS or older browsers, use a polyfill such as github/fetch, node-fetch or isomorphic-fetch. Alternatively, you can explicitly provide a fetch implementation using the @fetcher decorator function.

Usage

Use @remote to decorate Apis with a scoped isomorphic fetch method. Set server-side and client-side base-urls for fetching with @endpoint. Override the default fetcher (that uses global fetch) with @fetcher.

@remote(url='')

Decorate an Api class with @remote to give it it's own scoped version of fetch, just like it has scoped versions of getState and createAction.

@remote('http://example.com/api')
class App extends Api {
  someFunction() {
    return this.fetch('/products/Wedding+Dresses/')
      .then(() => {
        // here, fetch has completed successfully
      })
      .catch((error) => {
        // Something went wrong
      });
  }
}

Or, without relying on the decorators proposal:

const App = remote('http://example.com/api')(
  class App extends Api {
    someFunction() {
      return this.fetch('/products/Wedding+Dresses/')
        .then(() => {
          // here, fetch has completed successfully
        })
        .catch((error) => {
          // Something went wrong
        });
    }
  }
)

In both cases, instances of App will get a fetch method that is scoped to the URLs that were assigned to it by @remote and it's parent Apis. This allows us to postpone decicions about those URLs to later/higher up the Api hierarchy.

We can use @remote on classes as well as instances. This allows us to only declare that we will be using .fetch, but postponing the assignment of the url to later:

@remote
class MyApi extends Api {
  doIt() {
    return this.fetch('/something');
  }
}

// ...later

const myApp = remote('http://example.com')(
  new MyApi()
)

myApp.doIt(); // fetches 'http://example.com/something'

.fetch(url='', opts=undefined, abs=false)

Any apis decorated with @remote will get a .fetch method that performs fetch calls scoped to the current api. When called, it will prefix the given url with the url set by @remote. It then traverse the api hierarchy upwards, looking for fetch methods. If it finds one, it delegates to the found method. This allows us to map our entire Api hierarchy onto urls very easily:

@remote
class Module extends Api {
  doIt() {
    return this.fetch('/something');
  }
}

@remote
class ComplexModule extends Api {
  constructor(state) {
    super(state);
    this.submodule1 = remote('/sub1')(link(this, new Module()));
    this.submodule2 = remote('/sub2')(link(this, new Module()));
  }
}

@remote('http://example.com')
class App extends Api {
  constructor(state) {
    super(state);
    this.moduleA = remote('/modA')(link(this, new Module()));
    this.moduleB = remote('/modB')(link(this, new Module()));
    this.moduleC = remote('/modC')(link(this, new ComplexModule()));
  }
}

const app = new App().init();
app.moduleA.doIt(); // fetches 'http://example.com/modA/something'
app.moduleB.doIt(); // fetches 'http://example.com/modB/something'
app.moduleC.submodule1.doIt(); // fetches 'http://example.com/modC/sub1/something'
app.moduleC.submodule2.doIt(); // fetches 'http://example.com/modC/sub2/something'

@endpoint(url='', altUrl=null, usAlt=runningInBrowser())

Allows you to intervene in the process by which .fetch traverses the parent hierarchy. If it encounters an api with a fetch method and that api is decorated with @endpoint, it will stop traversing at that api and no longer look at the parent of that api.

This allows us to map our api hierarchy to multiple endpoints:

@remote
class Search extends Api {}

@remote('http://example.com/api')
class App extends Api {
  constructor(state){
    super(state);

    this.products = endpoint('http://products.example.com')(
      link(this, new Search())
    )
    this.people = remote('/people')(
      link(this, new Search())
    )
  }
}
app.products.fetch();  // fetches 'http://products.example.com'
app.people.fetch();    // fetches 'http://example.com/api/people'

The parameter altUrl allows us to use different urls in different environments. When specified, it will be used if parameter useAlt is truthy. useAlt is initialized to the result of runningInBrowser() by default, meaning altUrl will be used when running in a browser environment. You can easily use your own test conditions here.

@fetcher(fetchMethod)

This decoration allows you to override the default fetch method on any api you decorate with it. Whether the overridden fetch method is actually used depends on the position of the api in the hierarchy (due to .fetch traversing it's parents). As such you should set this on the top-level api and any apis decorated with @endpoint.

This library's test scripts make heavy use of @fetcher to replace the default fetch method from isomorphic-fetch with a stub that only tracks which urls have been fetched.

See also

If you are working with fetch, then you are doing async work. If you inherit from Async instead of from Api, you get async state management for free.

Feedback, suggestions, questions, bugs

Please visit the issue tracker for any of the above. Don't be afraid about being off-topic. Constructive feedback most appreciated!

Copyright

© 2016, Stijn de Witt. Some rights reserved.

License

Creative Commons Attribution 4.0 (CC-BY-4.0)