Code Monkey home page Code Monkey logo

atomic's Introduction

Atomic Build Status

A tiny, Promise-based vanilla JS Ajax/HTTP plugin with great browser support.

Download Atomic / View the demo


Want to learn how to write your own vanilla JS plugins? Check out my Vanilla JS Pocket Guides or join the Vanilla JS Academy and level-up as a web developer. ๐Ÿš€


Getting Started

Compiled and production-ready code can be found in the dist directory. The src directory contains development code.

1. Include Atomic on your site.

There are two versions of Atomic: the standalone version, and one that comes preloaded with a polyfill for ES6 Promises, which are only supported in newer browsers.

If you're including your own polyfill or don't want to enable this feature for older browsers, use the standalone version. Otherwise, use the version with the polyfill.

Direct Download

You can download the files directly from GitHub.

<script src="path/to/atomic.polyfills.min.js"></script>

CDN

You can also use the jsDelivr CDN. I recommend linking to a specific version number or version range to prevent major updates from breaking your site. Smooth Scroll uses semantic versioning.

<!-- Always get the latest version -->
<!-- Not recommended for production sites! -->
<script src="https://cdn.jsdelivr.net/gh/cferdinandi/atomic/dist/atomic.polyfills.min.js"></script>

<!-- Get minor updates and patch fixes within a major version -->
<script src="https://cdn.jsdelivr.net/gh/cferdinandi/atomic@4/dist/atomic.polyfills.min.js"></script>

<!-- Get patch fixes within a minor version -->
<script src="https://cdn.jsdelivr.net/gh/cferdinandi/[email protected]/dist/atomic.polyfills.min.js"></script>

<!-- Get a specific version -->
<script src="https://cdn.jsdelivr.net/gh/cferdinandi/[email protected]/dist/atomic.polyfills.min.js"></script>

NPM

You can also use NPM (or your favorite package manager).

npm install atomicjs

2. Make your Ajax request.

Pass in the requested URL, and optionally, your desired options. Request method defaults to GET.

Use .then() with a callback to handle successful responses, and catch() to handle errors.

// A basic GET request
atomic('https://some-url.com')
	.then(function (response) {
		console.log(response.data); // xhr.responseText
		console.log(response.xhr);  // full response
	})
	.catch(function (error) {
		console.log(error.status); // xhr.status
		console.log(error.statusText); // xhr.statusText
	});

// A POST request
atomic('https://some-url.com', {
	method: 'POST'
})
	.then(function (response) {
		console.log(response.data); // xhr.responseText
		console.log(response.xhr);  // full response
	})
	.catch(function (error) {
		console.log(error.status); // xhr.status
		console.log(error.statusText); // xhr.statusText
	});

ES6 Modules

Atomic does not have a default export, but does support CommonJS and can be used with native ES6 module imports.

import('/path/to/atomic.polyfills.min.js')
	.then(function () {
		atomic('https://some-url.com')
			.then(function (response) {
				console.log(response.data); // xhr.responseText
				console.log(response.xhr);  // full response
			})
			.catch(function (error) {
				console.log(error.status); // xhr.status
				console.log(error.statusText); // xhr.statusText
			});
	});

It uses a UMD pattern, and should also work in most major module bundlers and package managers.

Working with the Source Files

If you would prefer, you can work with the development code in the src directory using the included Gulp build system. This compiles, lints, and minifies code.

Dependencies

Make sure these are installed first.

Quick Start

  1. In bash/terminal/command line, cd into your project directory.
  2. Run npm install to install required files.
  3. When it's done installing, run one of the task runners to get going:
    • gulp manually compiles files.
    • gulp watch automatically compiles files when changes are made and applies changes using LiveReload.
    • gulp test runs unit tests.

Options and Settings

Atomic includes smart defaults and works right out of the box. You can pass options into Atomic through the ajax() function:

atomic('https://some-url.com', {
	method: 'GET', // {String} the request type
	username: null, // {String} an optional username for authentication purposes
	password: null, // {String} an optional password for authentication purposes
	data: {}, // {Object|Array|String} data to be sent to the server
	headers: { // {Object} Adds headers to your request: request.setRequestHeader(key, value)
		'Content-type': 'application/x-www-form-urlencoded'
	},
	responseType: 'text', // {String} the response type (https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/responseType)
	timeout: null, // {Integer} the number of milliseconds a request can take before automatically being terminated
	withCredentials: false // {Boolean} If true, send credentials with request (https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/withCredentials)
});

Canceling a Request

While Promises can't be canceled, Atomic does have an internal API for aborting your XHR request using the cancel() method.

In order to work, you must set your atomic() method to a variable without .then() methods. They can be called on the variable after setting.

// Setup your request
var xhr = atomic('https://some-url.com');

// Handle responses
xhr.then(function (response) {
		console.log(response.data); // xhr.responseText
		console.log(response.xhr);  // full response
	})
	.catch(function (error) {
		console.log(error.status); // xhr.status
		console.log(error.statusText); // xhr.statusText
	});

// Cancel your request
xhr.cancel();

Migrating from Atomic 3

New Features

  • Atomic is now Promise-based, and supports chaining with .then() and .catch().
  • For simple requests, you can now just pass in a URL to atomic() like you would with the Fetch API. You no longer need to pass in an object with the url parameter.

Breaking Changes

  • You must pass in a URL as the first argument. The URL as an options parameter is no longer support.
  • You now pass arguments directly into atomic(). The atomic.ajax() method no longer exists.
  • The .success(), .error(), and .always() callbacks have been removed. Use .then() and .catch() instead.
  • JSONP support has been removed.

You can still download Atomic 3 and earlier on the releases page.

Browser Compatibility

Atomic works in all modern browsers, and IE8 and above.

The standalone version provides native support for all modern browsers. Use the .polyfills version (or include your own) to support IE.

License

The code is available under the MIT License.

atomic's People

Contributors

agostinocinelli avatar cferdinandi avatar maikel-nait avatar robatron avatar toddmotto avatar vzwick avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

atomic's Issues

How to use Atomic properly (Browserify & Babel)

I tried to use Atomic as a dependency of my project and it was all good, until I wanted to make a change and start using Browserify and Babel. So before it worked fine as:

<script src="js/plugins/atomic.js"></script>
<script>
    atomic.get('/endpoint').success({});
</script>

But... Now it gives me error and throw me to line 35 as root is undefined.
var XHR = root.XMLHttpRequest || ActiveXObject;

The way I call it is:

import atomic from './plugins/atomic';

atomic.get('/endpoint').success({});

So that is failing... But this is working:

import atomic from './plugins/atomic';

const AJAX = atomic(window);

AJAX.get('/endpoint').success({});

Is that proper way of using it or is there a better way? I think I may be doing something wrong, so just making sure...

add additional headers

Maybe it would be nice to have an option to add additional headers.
For example to send a token to an API.

Maybe like jQuery:

atomic.get('someUrl', {
headers: {
"My-First-Header":"first value",
"AuthToken":"xxxxxxx"
}
});

Provide TypeScript type definition file

Currently the package provides no TypeScript type definitions which can make it not possible to use from TypeScript if you have strict mode on.

I created some type definitions below, they seem to work fine with one exception: atomicjs exports a function instead of an object with functions in it; the former is not allowed by ES6 so TypeScript is not happy and requires you to enable some compatibility switches to import it. Atomic exporting an object with a function in it would bring it in line with ES6 standards as I understand. But the following type definition matches the current stable package:

declare module "atomicjs" {
	type ResponseTypeStrings = "" | "arraybuffer" | "blob" | "document" | "json" | "text";
	type ResponseTypes<T> = 
		T extends "" ? string :
		T extends "arraybuffer" ? ArrayBuffer :
		T extends "blob" ? Blob :
		T extends "document" ? Document :
		T extends "json" ? any :
		T extends "text" ? string :
		never;

	type AtomicOptions = {
		method?: string,
		username?: string,
		password?: string,
		data?: object,
		headers?: Record<string, string>,
		timeout?: number,
		withCredentials?: boolean
	};
	
	type AtomicOptionsWithResponseType<T extends ResponseTypeStrings> = AtomicOptions & {
		responseType: T
	};
    
	type AtomicPromise<T> = Promise<T> & {
		cancel: () => void
	};

	function atomic(url: string, options: AtomicOptions | undefined): AtomicPromise<{data: string, xhr: XMLHttpRequest}>;
	function atomic<T extends ResponseTypeStrings>(url: string, options: AtomicOptionsWithResponseType<T>): AtomicPromise<{data: ResponseTypes<T>, xhr: XMLHttpRequest}>
	export = atomic;
}

Other possible areas for improvement include generic (eg <>) support for mapping JSON return values to a specific type.

I created this for use in a Chrome extension project, where I was compiling TypeScript down with webpack for the background service worker. My intention was to use a Promise-type model (using atomic) instead of XMLHttpRequest. But service workers don't support XML:HttpRequest so I couldn't use atomic anyway. But I don't want these definitions I wrote to go to waste.

Fluent callback assignment works for first callback only.

Due to the way the methods reference is passed back, the second callback is not assigned properly.

Steps to reproduce:

atomic.get('someResourceThatWillFail')
    .success(function () { console.log('success', arguments) })
    .error  (function () { console.log('error'  , arguments) });
// -> The error callback should be fired, but never will.

atomic.get('someResourceThatWillFail')
    .error  (function () { console.log('error'  , arguments) })
    .success(function () { console.log('success', arguments) });
// -> The error callback will be fired.

Vice versa:

atomic.get('someResourceThatWillSucceed')
    .success(function () { console.log('success', arguments) })
    .error  (function () { console.log('error'  , arguments) });
// -> The success callback will be fired.

atomic.get('someResourceThatWillSucceed')
    .error  (function () { console.log('error'  , arguments) })
    .success(function () { console.log('success', arguments) });
// -> The success callback should be fired, but never will.

X-Requested-With

"X-Requested-With: XMLHttpRequest" is not present in the Request Header? Why?
It would be useful to identify ajax request server side.

Thanks!

Document is confusing, references ajax but example uses atomic

In the README, the Options and Settings section says:

       Atomic includes smart defaults and works right out of the box. You can pass options into Atomic
       through the ajax() function:

but the example doesn't mention ajax:

atomic('https://s...

Should ajax() be atomic()?

-- rouilj

IE8 .delete() method quirk

With IE8, any methods named .delete() will throw an error. AngularJS also has the same "problem" in IE8. Using a delete method using Object dot notation will error your application.

The workaround is very simple, using bracket notation lookup rather than dot notation:

atomic['delete']
.success()
.error();

Publish to Git?

It seems the current code in dist (and in bower's dist) does not work (success and error callbacks cannot both be used simultaneously). It looks like the code in src folder is correct, but it has not been built and committed.

Converting from jquery

I'm quite new to JS, so I've being using jquery, but I would like to move to vanilla. I have this Ajax in jquery:

$('#category').change(function() {
	var categoryID = $(this).val();
	var dataURL = $(this).data('url') + 'taxonomy/get_sub/'+categoryID;

	$.ajax({
		url: dataURL,
		method: 'POST',
		success:function(data) {
			$('#sub_category').html(data);
		}
	});
});

Can I do the same thing with atomic?

Publish to NPM

Any chance you could publish this to NPM? Looks like atomic is taken but atomicjs is available.

By the way thanks for making this!

README.md slight mistake

I am not sure if that was intented or it's slight typo out there:

atomic.post('/endpoint'[, data])
atomic.put('/endpoint'[, data])

atomic.post('/endpoint', [data])
atomic.put('/endpoint', [data])

Unit tests

Docs say to run gulp test but that doesn't seem to work, there isn't any tests configured? Tests appear to be out of date as they use atomic.ajax? So basically it seems this library is currently not unit tested? ๐Ÿ˜ข

Use Promise-like syntax

As well as the .success() and .error() methods, potentially provide a promise-like syntax:

atomic.get()
.then(function () {
  // success
}, function () {
  // error
});

License?

Hello,

No license is specified. Just wondering what the conditions are surrounding using/extending/modifying your code?

Thanks!

Improve documentation

  1. Add details/examples on how to use the data setting.
  2. Add information on acceptable responseType types.

Missing v1.1.0 tag

Hi Todd, v1.1.0 tag is missing among Atomic releases!
It prevents Bower from getting 1.1.0 updates (unless setting the dependency to the last commit).

Not sure if make a pull request for so little thing. Greetings!

ActiveXObject is not defined

Hi!

The following code fails with 'Uncaught ReferenceError: ActiveXObject is not defined' message:

import * as atomic from 'atomic';

atomic.get(url.file)
  .success(function(data, xhr) {
    console.log('.success:', data, xhr);
  })
  .error(function(data, xhr) {
    console.log('.error:', data, xhr);
  })
  .always(function(data, xhr) {
    console.log('.always:', data, xhr);
  });

PS:
I'm using Babel + Webpack.

Add a way to abort requests

Atomic lacks a way to abort the current ajax requests. Useful, for example, when an user is using autocomplete functions and you want to abort previous requests to save resources and time.

It would be great to have something like that.

var ajaxRequest = atomic.get( "/endpoint" );
// aborting the request
ajaxRequest.abort();

Push current version to npm

Please push the current version to npm and update the readme to suggest using the jsdelivr npmjs urls over the /gh/ urls as they recommend.

Thanks for this library!

Issen't working on IE8+

I'm getting:

Access is denied.
atomic.js, line 43 character 5

The error seems to be in the request open.

When Object is passed, content-type is form-urlencoded

When an object is passed, the content type should be transparently set to JSON yet it is:
"application/x-www-form-urlencoded"
This causes objects that contain other objects to be converted to the "[object Object]" string.

Add ability to set headers map

I'm sorry if this is already possible but I could't find it in the source code, but if it is possible this issue should be for adding it to the documentation.

Consider adding common method shortcuts

Would be awesome if common methods could be added:

atomic.post('https://www.test.com', [data], [config]).then(...)
atomic.get('https://www.test.com', [data], [config]).then(...)

This is much nicer and more explicit than doing:

atomic('https://www.test.com', { method: 'POST' })
atomic('https://www.test.com')

(I realise get is shorter as it's the default method, but it's worth adding for consistency)

This might coincide with #68 if you could get the atomic instance and call methods / set defaults etc.

Make it possible to provide FormData transparently

Hey,

I really like the simplicity of atomic.js. Yesterday I ran into a problem, though.

I want to upload a file via a FormData. However if I provide FormData to atomic.js (in contrast to just a simple object) it fails.

Would it be possible to enhance atomic.js so that if provided data is of type FormData atomic just passes it through to the xhr request?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.