(function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : typeof define === 'function' && define.amd ? define(factory) : (global.Promise = factory()); }(this, (function () { 'use strict'; /** * async function * * @syntax: * async function() {} * async () => {} * async x() => {} * * @compatibility * IE: no * Edge: >= 15 * Android: >= 5.0 * */ function isAsyncFunction (fn) { return ( {} ).toString.call( fn ) === '[object AsyncFunction]'; } function isFunction (fn) { return ({}).toString.call( fn ) === '[object Function]' || isAsyncFunction( fn ); } function isPromise (p) { return p && isFunction( p.then ); } var Promise = (function () { function Promise( fn ) { if( !( this instanceof Promise ) ) { throw new TypeError( this + ' is not a promise ' ); } if( !isFunction( fn ) ) { throw new TypeError( 'Promise resolver ' + fn + ' is not a function' ); } this[ '[[PromiseStatus]]' ] = 'pending'; this[ '[[PromiseValue]]' ]= null; this[ '[[PromiseThenables]]' ] = []; try { fn( promiseResolve.bind( null, this ), promiseReject.bind( null, this ) ); } catch( e ) { if( this[ '[[PromiseStatus]]' ] === 'pending' ) { promiseReject.bind( null, this )( e ); } } } Promise.prototype.then = function then ( resolved, rejected ) { var promise = new Promise( function () {} ); this[ '[[PromiseThenables]]' ].push( { resolve : isFunction( resolved ) ? resolved : null, reject : isFunction( rejected ) ? rejected : null, called : false, promise: promise } ); if( this[ '[[PromiseStatus]]' ] !== 'pending' ) { promiseExecute( this ); } return promise; }; Promise.prototype.catch = function catch$1 ( reject ) { return this.then( null, reject ); }; return Promise; }()); Promise.resolve = function( value ) { if( !isFunction( this ) ) { throw new TypeError( 'Promise.resolve is not a constructor' ); } /** * @todo * check if the value need to return the resolve( value ) */ return new Promise( function (resolve) { resolve( value ); } ); }; Promise.reject = function( reason ) { if( !isFunction( this ) ) { throw new TypeError( 'Promise.reject is not a constructor' ); } return new Promise( function ( resolve, reject ) { reject( reason ); } ); }; Promise.all = function( promises ) { var rejected = false; var res = []; return new Promise( function ( resolve, reject ) { var remaining = 0; var then = function ( p, i ) { if( !isPromise( p ) ) { p = Promise.resolve( p ); } p.then( function (value) { res[ i ] = value; setTimeout( function () { if( --remaining === 0 ) { resolve( res ); } }, 0 ); }, function (reason) { if( !rejected ) { reject( reason ); rejected = true; } } ); }; var i = 0; for( var i$1 = 0, list = promises; i$1 < list.length; i$1 += 1 ) { var promise = list[i$1]; remaining++; then( promise, i++ ); } if( !i ) { resolve( res ); } } ); }; Promise.race = function( promises ) { var resolved = false; var rejected = false; return new Promise( function ( resolve, reject ) { function onresolved( value ) { if( !resolved && !rejected ) { resolve( value ); resolved = true; } } function onrejected( reason ) { if( !resolved && !rejected ) { reject( reason ); rejected = true; } } for( var i = 0, list = promises; i < list.length; i += 1 ) { var promise = list[i]; if( !isPromise( promise ) ) { promise = Promise.resolve( promise ); } promise.then( onresolved, onrejected ); } } ); }; function promiseExecute( promise ) { var thenable, p; if( promise[ '[[PromiseStatus]]' ] === 'pending' ) { return; } if( !promise[ '[[PromiseThenables]]' ].length ) { return; } var then = function ( p, t ) { p.then( function (value) { promiseResolve( t.promise, value ); }, function (reason) { promiseReject( t.promise, reason ); } ); }; while( promise[ '[[PromiseThenables]]' ].length ) { thenable = promise[ '[[PromiseThenables]]' ].shift(); if( thenable.called ) { continue; } thenable.called = true; if( promise[ '[[PromiseStatus]]' ] === 'resolved' ) { if( !thenable.resolve ) { promiseResolve( thenable.promise, promise[ '[[PromiseValue]]' ] ); continue; } try { p = thenable.resolve.call( null, promise[ '[[PromiseValue]]' ] ); } catch( e ) { then( Promise.reject( e ), thenable ); continue; } if( p && ( typeof p === 'function' || typeof p === 'object' ) && p.then ) { then( p, thenable ); continue; } } else { if( !thenable.reject ) { promiseReject( thenable.promise, promise[ '[[PromiseValue]]' ] ); continue; } try { p = thenable.reject.call( null, promise[ '[[PromiseValue]]' ] ); } catch( e ) { then( Promise.reject( e ), thenable ); continue; } if( ( typeof p === 'function' || typeof p === 'object' ) && p.then ) { then( p, thenable ); continue; } } promiseResolve( thenable.promise, p ); } return promise; } function promiseResolve( promise, value ) { if( !( promise instanceof Promise ) ) { return new Promise( function (resolve) { resolve( value ); } ); } if( promise[ '[[PromiseStatus]]' ] !== 'pending' ) { return; } if( value === promise ) { /** * thie error should be thrown, defined ES6 standard * it would be thrown in Chrome but not in Firefox or Safari */ throw new TypeError( 'Chaining cycle detected for promise #' ); } if( value !== null && ( typeof value === 'function' || typeof value === 'object' ) ) { var then; try { then = value.then; } catch( e ) { return promiseReject( promise, e ); } if( typeof then === 'function' ) { then.call( value, promiseResolve.bind( null, promise ), promiseReject.bind( null, promise ) ); return; } } promise[ '[[PromiseStatus]]' ] = 'resolved'; promise[ '[[PromiseValue]]' ] = value; promiseExecute( promise ); } function promiseReject( promise, value ) { if( !( promise instanceof Promise ) ) { return new Promise( function ( resolve, reject ) { reject( value ); } ); } promise[ '[[PromiseStatus]]' ] = 'rejected'; promise[ '[[PromiseValue]]' ] = value; promiseExecute( promise ); } return Promise; })));