fetch请求php的坑,使用fetch遇到过的坑

前段时间在项目中用到了这个fetch 来代替Ajax 进行网络请求。也踩了不少的坑,在这边列举出来以及他的解决方法。

1.如何保持每次请求的会话一致?

在用fetch进行网络请求的时候,发现每次请求到服务端的时候,他的sessionId 都是不一样的,后面排查原来是在请求的时候fetch默认是不会带上本地jsessionId,以至于服务端无法接收到,所以会重新创建一个新的session。

解决办法:

var init = {

credentials: 'include' // 请求带上cookies,是每次请求保持会话一直

...

}

2.兼容性,支持IE10+、谷歌、火狐等

由于fetch是一个新技术,有些旧的浏览器对它并不支持,这时候要怎么兼容?

解决办法:

引入一个额外的补丁es6-promise.js可以使它很好的支持IE9以上的版本,那IE8呢?IE8 需要改fetch.js源码才能支持

fetch.js 只需改两处:

456747.html

456747.html

try里面的是源码本身的,catch里面的是小编额外加的。细心的会发现这两处改的是一样的,都是对getOwnPropertyNames进行替换。但是IE8也不支持forEach为啥没有替换    呢? 其实有替换了,只是不再这边体现。我把它写进了Array.prototype里面了,其实fetch.js里面也用到了indexOf,它在IE8下也是不支持,我把它一并的放在Array.prototype

代码如下:Array.prototype.forEach = function(callback, thisArg) {

var T, k;

if (this == null) {

throw new TypeError(" this is null or not defined");

}

var O = Object(this);

var len = O.length >>> 0; // Hack to convert O.length to a UInt32

if ({}.toString.call(callback) != "[object Function]") {

throw new TypeError(callback + " is not a function");

}

if (thisArg) {

T = thisArg;

}

k = 0;

while (k < len) {

var kValue;

if (k in O) {

kValue = O[k];

callback.call(T, kValue, k, O);

}

k++;

}

};

if (!Array.prototype.indexOf)

{

Array.prototype.indexOf = function(elt /*, from*/)

{

var len = this.length >>> 0;

var from = Number(arguments[1]) || 0;

from = (from < 0)

? Math.ceil(from)

: Math.floor(from);

if (from < 0)

from += len;

for (; from < len; from++)

{

if (from in this &&

this[from] === elt)

return from;

}

return -1;

};

};

最后附上修改后的文件以及自己封装的一个网络请求request.js。

request.js:

/**

* 该方法仅支持IE8以上

* 网络请求方法

* url:请求地址

* options = {

* catchs: 异常处理,控制台抛出的异常是否自己处理:true 是,false 否 由公共方法统一处理优化显示给用户 默认 false

* credentials: 请求带上cookies,是每次请求保持会话一直

* method: 请求使用的方法,如 GET、POST

* headers: 请求的头信息,形式为 Headers 对象或 ByteString。

* body: 请求的 body 信息:可能是一个 Blob、BufferSource、FormData、URLSearchParams 或者 USVString 对象。注意 GET 或 HEAD 方法的请求不能包含 body 信息。

* mode: 请求的模式,如 cors、no-cors 或者same-origin。是否允许跨域请求

* cache: 请求的 cache 模式: default, no-store, reload, no-cache, force-cache, or only-if-cached.

* }

*/

var $requst = function (url, options) {

var myHeaders = {

'Content-Type': 'text/html; charset=utf-8'

};

var init = {

credentials: 'include',

method: (options && options.method) || 'GET',

headers: (options && options.headers) || myHeaders,

cache: (options && options.cache) || 'default'

}

if (options && options.body) {

init.body = JSON.stringify(options.body)

}

return fetch(url, init)

.then(function(response) {

if (response.ok) {

return _returnContentByType(response);

} else {

if (options && options.catchs) {

throw new Error(response.statusText);

} else {

var error = new Error(response.statusText);

throw new Error('');

}

}

});

};

/**

* 根据type返回不同格式的response

*/

var _returnContentByType = function (response) {

var type = response.headers.get('Content-Type').split(";")[0];

switch (type) {

case 'text/html':

return response.text();

break

case 'application/json':

return response.json();

break

default:

}

};

fetch.js:

(function() {

'use strict';

// if __disableNativeFetch is set to true, the it will always polyfill fetch

// with Ajax.

if (!self.__disableNativeFetch && self.fetch) {

return

}

function normalizeName(name) {

if (typeof name !== 'string') {

name = String(name)

}

if (/[^a-z0-9\-#$%&'*+.\^_`|~]/i.test(name)) {

throw new TypeError('Invalid character in header field name')

}

return name.toLowerCase()

}

function normalizeValue(value) {

if (typeof value !== 'string') {

value = String(value)

}

return value

}

function Headers(headers) {

this.map = {}

if (headers instanceof Headers) {

headers.forEach(function(value, name) {

this.append(name, value)

}, this)

} else if (headers) {

try{

Object.getOwnPropertyNames(headers).forEach(function(name) {

this.append(name, headers[name])

}, this)

}catch(e){

var a = [];

for (var i in headers) {

if (headers.hasOwnProperty(i)) {

a.push(i); // 输出 foo asj

}

};

a.forEach(function(name) {

this.append(name, headers[name])

}, this)

}

}

}

Headers.prototype.append = function(name, value) {

name = normalizeName(name)

value = normalizeValue(value)

var list = this.map[name]

if (!list) {

list = []

this.map[name] = list

}

list.push(value)

}

Headers.prototype['delete'] = function(name) {

delete this.map[normalizeName(name)]

}

Headers.prototype.get = function(name) {

var values = this.map[normalizeName(name)]

return values ? values[0] : null

}

Headers.prototype.getAll = function(name) {

return this.map[normalizeName(name)] || []

}

Headers.prototype.has = function(name) {

return this.map.hasOwnProperty(normalizeName(name))

}

Headers.prototype.set = function(name, value) {

this.map[normalizeName(name)] = [normalizeValue(value)]

}

Headers.prototype.forEach = function(callback, thisArg) {

try{

Object.getOwnPropertyNames(this.map).forEach(function(name) {

this.map[name].forEach(function(value) {

callback.call(thisArg, value, name, this)

}, this)

}, this)

}catch(e){

var a = [];

for (var i in this.map) {

if (this.map.hasOwnProperty(i)) {

a.push(i); // 输出 foo asj

}

};

a.forEach(function(name) {

this.map[name].forEach(function(value) {

callback.call(thisArg, value, name, this)

}, this)

}, this)

}

}

function consumed(body) {

if (body.bodyUsed) {

return Promise.reject(new TypeError('Already read'))

}

body.bodyUsed = true

}

function fileReaderReady(reader) {

return new Promise(function(resolve, reject) {

reader.onload = function() {

resolve(reader.result)

}

reader.onerror = function() {

reject(reader.error)

}

})

}

function readBlobAsArrayBuffer(blob) {

var reader = new FileReader()

reader.readAsArrayBuffer(blob)

return fileReaderReady(reader)

}

function readBlobAsText(blob, options) {

var reader = new FileReader()

var contentType = options.headers.map['content-type'] ? options.headers.map['content-type'].toString() : ''

var regex = /charset\=[0-9a-zA-Z\-\_]*;?/

var _charset = blob.type.match(regex) || contentType.match(regex)

var args = [blob]

if(_charset) {

args.push(_charset[0].replace(/^charset\=/, '').replace(/;$/, ''))

}

reader.readAsText.apply(reader, args)

return fileReaderReady(reader)

}

var support = {

blob: 'FileReader' in self && 'Blob' in self && (function() {

try {

new Blob();

return true

} catch(e) {

return false

}

})(),

formData: 'FormData' in self,

arrayBuffer: 'ArrayBuffer' in self

}

function Body() {

this.bodyUsed = false

this._initBody = function(body, options) {

this._bodyInit = body

if (typeof body === 'string') {

this._bodyText = body

} else if (support.blob && Blob.prototype.isPrototypeOf(body)) {

this._bodyBlob = body

this._options = options

} else if (support.formData && FormData.prototype.isPrototypeOf(body)) {

this._bodyFormData = body

} else if (!body) {

this._bodyText = ''

} else if (support.arrayBuffer && ArrayBuffer.prototype.isPrototypeOf(body)) {

// Only support ArrayBuffers for POST method.

// Receiving ArrayBuffers happens via Blobs, instead.

} else {

throw new Error('unsupported BodyInit type')

}

}

if (support.blob) {

this.blob = function() {

var rejected = consumed(this)

if (rejected) {

return rejected

}

if (this._bodyBlob) {

return Promise.resolve(this._bodyBlob)

} else if (this._bodyFormData) {

throw new Error('could not read FormData body as blob')

} else {

return Promise.resolve(new Blob([this._bodyText]))

}

}

this.arrayBuffer = function() {

return this.blob().then(readBlobAsArrayBuffer)

}

this.text = function() {

var rejected = consumed(this)

if (rejected) {

return rejected

}

if (this._bodyBlob) {

return readBlobAsText(this._bodyBlob, this._options)

} else if (this._bodyFormData) {

throw new Error('could not read FormData body as text')

} else {

return Promise.resolve(this._bodyText)

}

}

} else {

this.text = function() {

var rejected = consumed(this)

return rejected ? rejected : Promise.resolve(this._bodyText)

}

}

if (support.formData) {

this.formData = function() {

return this.text().then(decode)

}

}

this.json = function() {

return this.text().then(JSON.parse)

}

return this

}

// HTTP methods whose capitalization should be normalized

var methods = ['DELETE', 'GET', 'HEAD', 'OPTIONS', 'POST', 'PUT']

function normalizeMethod(method) {

var upcased = method.toUpperCase()

return (methods.indexOf(upcased) > -1) ? upcased : method

}

function Request(input, options) {

options = options || {}

var body = options.body

if (Request.prototype.isPrototypeOf(input)) {

if (input.bodyUsed) {

throw new TypeError('Already read')

}

this.url = input.url

this.credentials = input.credentials

if (!options.headers) {

this.headers = new Headers(input.headers)

}

this.method = input.method

this.mode = input.mode

if (!body) {

body = input._bodyInit

input.bodyUsed = true

}

} else {

this.url = input

}

this.credentials = options.credentials || this.credentials || 'omit'

if (options.headers || !this.headers) {

this.headers = new Headers(options.headers)

}

this.method = normalizeMethod(options.method || this.method || 'GET')

this.mode = options.mode || this.mode || null

this.referrer = null

if ((this.method === 'GET' || this.method === 'HEAD') && body) {

throw new TypeError('Body not allowed for GET or HEAD requests')

}

this._initBody(body, options)

}

Request.prototype.clone = function() {

return new Request(this)

}

function decode(body) {

var form = new FormData()

body.trim().split('&').forEach(function(bytes) {

if (bytes) {

var split = bytes.split('=')

var name = split.shift().replace(/\+/g, ' ')

var value = split.join('=').replace(/\+/g, ' ')

form.append(decodeURIComponent(name), decodeURIComponent(value))

}

})

return form

}

function headers(xhr) {

var head = new Headers()

var pairs = xhr.getAllResponseHeaders().trim().split('\n')

pairs.forEach(function(header) {

var split = header.trim().split(':')

var key = split.shift().trim()

var value = split.join(':').trim()

head.append(key, value)

})

return head

}

Body.call(Request.prototype)

function Response(bodyInit, options) {

if (!options) {

options = {}

}

this._initBody(bodyInit, options)

this.type = 'default'

this.status = options.status

this.ok = this.status >= 200 && this.status < 300

this.statusText = options.statusText

this.headers = options.headers instanceof Headers ? options.headers : new Headers(options.headers)

this.url = options.url || ''

}

Body.call(Response.prototype)

Response.prototype.clone = function() {

return new Response(this._bodyInit, {

status: this.status,

statusText: this.statusText,

headers: new Headers(this.headers),

url: this.url

})

}

Response.error = function() {

var response = new Response(null, {status: 0, statusText: ''})

response.type = 'error'

return response

}

var redirectStatuses = [301, 302, 303, 307, 308]

Response.redirect = function(url, status) {

if (redirectStatuses.indexOf(status) === -1) {

throw new RangeError('Invalid status code')

}

return new Response(null, {status: status, headers: {location: url}})

}

self.Headers = Headers;

self.Request = Request;

self.Response = Response;

self.fetch = function(input, init) {

return new Promise(function(resolve, reject) {

var request

if (Request.prototype.isPrototypeOf(input) && !init) {

request = input

} else {

request = new Request(input, init)

}

var xhr = new XMLHttpRequest()

function responseURL() {

if ('responseURL' in xhr) {

return xhr.responseURL

}

// Avoid security warnings on getResponseHeader when not allowed by CORS

if (/^X-Request-URL:/m.test(xhr.getAllResponseHeaders())) {

return xhr.getResponseHeader('X-Request-URL')

}

return;

}

var __onLoadHandled = false;

function onload() {

if (xhr.readyState !== 4) {

return

}

var status = (xhr.status === 1223) ? 204 : xhr.status

if (status < 100 || status > 599) {

if (__onLoadHandled) { return; } else { __onLoadHandled = true; }

reject(new TypeError('Network request failed'))

return

}

var options = {

status: status,

statusText: xhr.statusText,

headers: headers(xhr),

url: responseURL()

}

var body = 'response' in xhr ? xhr.response : xhr.responseText;

if (__onLoadHandled) { return; } else { __onLoadHandled = true; }

resolve(new Response(body, options))

}

xhr.onreadystatechange = onload;

xhr.onload = onload;

xhr.onerror = function() {

if (__onLoadHandled) { return; } else { __onLoadHandled = true; }

reject(new TypeError('Network request failed'))

}

xhr.open(request.method, request.url, true)

// `withCredentials` should be setted after calling `.open` in IE10

// http://stackoverflow.com/a/19667959/1219343

try {

if (request.credentials === 'include') {

if ('withCredentials' in xhr) {

xhr.withCredentials = true;

} else {

console && console.warn && console.warn('withCredentials is not supported, you can ignore this warning');

}

}

} catch (e) {

console && console.warn && console.warn('set withCredentials error:' + e);

}

if ('responseType' in xhr && support.blob) {

xhr.responseType = 'blob'

}

request.headers.forEach(function(value, name) {

xhr.setRequestHeader(name, value)

})

xhr.send(typeof request._bodyInit === 'undefined' ? null : request._bodyInit)

})

}

self.fetch.polyfill = true

// Support CommonJS

if (typeof module !== 'undefined' && module.exports) {

module.exports = self.fetch;

}

})();

es6-promise.js:/*!

* @overview es6-promise - a tiny implementation of Promises/A+.

* @copyright Copyright (c) 2014 Yehuda Katz, Tom Dale, Stefan Penner and contributors (Conversion to ES6 API by Jake Archibald)

* @license Licensed under MIT license

* See https://raw.githubusercontent.com/stefanpenner/es6-promise/master/LICENSE

* @version 3.2.2+39aa2571

*/

(function() {

"use strict";

function lib$es6$promise$utils$$objectOrFunction(x) {

return typeof x === 'function' || (typeof x === 'object' && x !== null);

}

function lib$es6$promise$utils$$isFunction(x) {

return typeof x === 'function';

}

function lib$es6$promise$utils$$isMaybeThenable(x) {

return typeof x === 'object' && x !== null;

}

var lib$es6$promise$utils$$_isArray;

if (!Array.isArray) {

lib$es6$promise$utils$$_isArray = function (x) {

return Object.prototype.toString.call(x) === '[object Array]';

};

} else {

lib$es6$promise$utils$$_isArray = Array.isArray;

}

var lib$es6$promise$utils$$isArray = lib$es6$promise$utils$$_isArray;

var lib$es6$promise$asap$$len = 0;

var lib$es6$promise$asap$$vertxNext;

var lib$es6$promise$asap$$customSchedulerFn;

var lib$es6$promise$asap$$asap = function asap(callback, arg) {

lib$es6$promise$asap$$queue[lib$es6$promise$asap$$len] = callback;

lib$es6$promise$asap$$queue[lib$es6$promise$asap$$len + 1] = arg;

lib$es6$promise$asap$$len += 2;

if (lib$es6$promise$asap$$len === 2) {

// If len is 2, that means that we need to schedule an async flush.

// If additional callbacks are queued before the queue is flushed, they

// will be processed by this flush that we are scheduling.

if (lib$es6$promise$asap$$customSchedulerFn) {

lib$es6$promise$asap$$customSchedulerFn(lib$es6$promise$asap$$flush);

} else {

lib$es6$promise$asap$$scheduleFlush();

}

}

}

function lib$es6$promise$asap$$setScheduler(scheduleFn) {

lib$es6$promise$asap$$customSchedulerFn = scheduleFn;

}

function lib$es6$promise$asap$$setAsap(asapFn) {

lib$es6$promise$asap$$asap = asapFn;

}

var lib$es6$promise$asap$$browserWindow = (typeof window !== 'undefined') ? window : undefined;

var lib$es6$promise$asap$$browserGlobal = lib$es6$promise$asap$$browserWindow || {};

var lib$es6$promise$asap$$BrowserMutationObserver = lib$es6$promise$asap$$browserGlobal.MutationObserver || lib$es6$promise$asap$$browserGlobal.WebKitMutationObserver;

var lib$es6$promise$asap$$isNode = typeof self === 'undefined' && typeof process !== 'undefined' && {}.toString.call(process) === '[object process]';

// test for web worker but not in IE10

var lib$es6$promise$asap$$isWorker = typeof Uint8ClampedArray !== 'undefined' &&

typeof importScripts !== 'undefined' &&

typeof MessageChannel !== 'undefined';

// node

function lib$es6$promise$asap$$useNextTick() {

// node version 0.10.x displays a deprecation warning when nextTick is used recursively

// see https://github.com/cujojs/when/issues/410 for details

return function() {

process.nextTick(lib$es6$promise$asap$$flush);

};

}

// vertx

function lib$es6$promise$asap$$useVertxTimer() {

return function() {

lib$es6$promise$asap$$vertxNext(lib$es6$promise$asap$$flush);

};

}

function lib$es6$promise$asap$$useMutationObserver() {

var iterations = 0;

var observer = new lib$es6$promise$asap$$BrowserMutationObserver(lib$es6$promise$asap$$flush);

var node = document.createTextNode('');

observer.observe(node, { characterData: true });

return function() {

node.data = (iterations = ++iterations % 2);

};

}

// web worker

function lib$es6$promise$asap$$useMessageChannel() {

var channel = new MessageChannel();

channel.port1.onmessage = lib$es6$promise$asap$$flush;

return function () {

channel.port2.postMessage(0);

};

}

function lib$es6$promise$asap$$useSetTimeout() {

return function() {

setTimeout(lib$es6$promise$asap$$flush, 1);

};

}

var lib$es6$promise$asap$$queue = new Array(1000);

function lib$es6$promise$asap$$flush() {

for (var i = 0; i < lib$es6$promise$asap$$len; i+=2) {

var callback = lib$es6$promise$asap$$queue[i];

var arg = lib$es6$promise$asap$$queue[i+1];

callback(arg);

lib$es6$promise$asap$$queue[i] = undefined;

lib$es6$promise$asap$$queue[i+1] = undefined;

}

lib$es6$promise$asap$$len = 0;

}

function lib$es6$promise$asap$$attemptVertx() {

try {

var r = require;

var vertx = r('vertx');

lib$es6$promise$asap$$vertxNext = vertx.runOnLoop || vertx.runOnContext;

return lib$es6$promise$asap$$useVertxTimer();

} catch(e) {

return lib$es6$promise$asap$$useSetTimeout();

}

}

var lib$es6$promise$asap$$scheduleFlush;

// Decide what async method to use to triggering processing of queued callbacks:

if (lib$es6$promise$asap$$isNode) {

lib$es6$promise$asap$$scheduleFlush = lib$es6$promise$asap$$useNextTick();

} else if (lib$es6$promise$asap$$BrowserMutationObserver) {

lib$es6$promise$asap$$scheduleFlush = lib$es6$promise$asap$$useMutationObserver();

} else if (lib$es6$promise$asap$$isWorker) {

lib$es6$promise$asap$$scheduleFlush = lib$es6$promise$asap$$useMessageChannel();

} else if (lib$es6$promise$asap$$browserWindow === undefined && typeof require === 'function') {

lib$es6$promise$asap$$scheduleFlush = lib$es6$promise$asap$$attemptVertx();

} else {

lib$es6$promise$asap$$scheduleFlush = lib$es6$promise$asap$$useSetTimeout();

}

function lib$es6$promise$then$$then(onFulfillment, onRejection) {

var parent = this;

var child = new this.constructor(lib$es6$promise$$internal$$noop);

if (child[lib$es6$promise$$internal$$PROMISE_ID] === undefined) {

lib$es6$promise$$internal$$makePromise(child);

}

var state = parent._state;

if (state) {

var callback = arguments[state - 1];

lib$es6$promise$asap$$asap(function(){

lib$es6$promise$$internal$$invokeCallback(state, child, callback, parent._result);

});

} else {

lib$es6$promise$$internal$$subscribe(parent, child, onFulfillment, onRejection);

}

return child;

}

var lib$es6$promise$then$$default = lib$es6$promise$then$$then;

function lib$es6$promise$promise$resolve$$resolve(object) {

/*jshint validthis:true */

var Constructor = this;

if (object && typeof object === 'object' && object.constructor === Constructor) {

return object;

}

var promise = new Constructor(lib$es6$promise$$internal$$noop);

lib$es6$promise$$internal$$resolve(promise, object);

return promise;

}

var lib$es6$promise$promise$resolve$$default = lib$es6$promise$promise$resolve$$resolve;

var lib$es6$promise$$internal$$PROMISE_ID = Math.random().toString(36).substring(16);

function lib$es6$promise$$internal$$noop() {}

var lib$es6$promise$$internal$$PENDING = void 0;

var lib$es6$promise$$internal$$FULFILLED = 1;

var lib$es6$promise$$internal$$REJECTED = 2;

var lib$es6$promise$$internal$$GET_THEN_ERROR = new lib$es6$promise$$internal$$ErrorObject();

function lib$es6$promise$$internal$$selfFulfillment() {

return new TypeError("You cannot resolve a promise with itself");

}

function lib$es6$promise$$internal$$cannotReturnOwn() {

return new TypeError('A promises callback cannot return that same promise.');

}

function lib$es6$promise$$internal$$getThen(promise) {

try {

return promise.then;

} catch(error) {

lib$es6$promise$$internal$$GET_THEN_ERROR.error = error;

return lib$es6$promise$$internal$$GET_THEN_ERROR;

}

}

function lib$es6$promise$$internal$$tryThen(then, value, fulfillmentHandler, rejectionHandler) {

try {

then.call(value, fulfillmentHandler, rejectionHandler);

} catch(e) {

return e;

}

}

function lib$es6$promise$$internal$$handleForeignThenable(promise, thenable, then) {

lib$es6$promise$asap$$asap(function(promise) {

var sealed = false;

var error = lib$es6$promise$$internal$$tryThen(then, thenable, function(value) {

if (sealed) { return; }

sealed = true;

if (thenable !== value) {

lib$es6$promise$$internal$$resolve(promise, value);

} else {

lib$es6$promise$$internal$$fulfill(promise, value);

}

}, function(reason) {

if (sealed) { return; }

sealed = true;

lib$es6$promise$$internal$$reject(promise, reason);

}, 'Settle: ' + (promise._label || ' unknown promise'));

if (!sealed && error) {

sealed = true;

lib$es6$promise$$internal$$reject(promise, error);

}

}, promise);

}

function lib$es6$promise$$internal$$handleOwnThenable(promise, thenable) {

if (thenable._state === lib$es6$promise$$internal$$FULFILLED) {

lib$es6$promise$$internal$$fulfill(promise, thenable._result);

} else if (thenable._state === lib$es6$promise$$internal$$REJECTED) {

lib$es6$promise$$internal$$reject(promise, thenable._result);

} else {

lib$es6$promise$$internal$$subscribe(thenable, undefined, function(value) {

lib$es6$promise$$internal$$resolve(promise, value);

}, function(reason) {

lib$es6$promise$$internal$$reject(promise, reason);

});

}

}

function lib$es6$promise$$internal$$handleMaybeThenable(promise, maybeThenable, then) {

if (maybeThenable.constructor === promise.constructor &&

then === lib$es6$promise$then$$default &&

constructor.resolve === lib$es6$promise$promise$resolve$$default) {

lib$es6$promise$$internal$$handleOwnThenable(promise, maybeThenable);

} else {

if (then === lib$es6$promise$$internal$$GET_THEN_ERROR) {

lib$es6$promise$$internal$$reject(promise, lib$es6$promise$$internal$$GET_THEN_ERROR.error);

} else if (then === undefined) {

lib$es6$promise$$internal$$fulfill(promise, maybeThenable);

} else if (lib$es6$promise$utils$$isFunction(then)) {

lib$es6$promise$$internal$$handleForeignThenable(promise, maybeThenable, then);

} else {

lib$es6$promise$$internal$$fulfill(promise, maybeThenable);

}

}

}

function lib$es6$promise$$internal$$resolve(promise, value) {

if (promise === value) {

lib$es6$promise$$internal$$reject(promise, lib$es6$promise$$internal$$selfFulfillment());

} else if (lib$es6$promise$utils$$objectOrFunction(value)) {

lib$es6$promise$$internal$$handleMaybeThenable(promise, value, lib$es6$promise$$internal$$getThen(value));

} else {

lib$es6$promise$$internal$$fulfill(promise, value);

}

}

function lib$es6$promise$$internal$$publishRejection(promise) {

if (promise._onerror) {

promise._onerror(promise._result);

}

lib$es6$promise$$internal$$publish(promise);

}

function lib$es6$promise$$internal$$fulfill(promise, value) {

if (promise._state !== lib$es6$promise$$internal$$PENDING) { return; }

promise._result = value;

promise._state = lib$es6$promise$$internal$$FULFILLED;

if (promise._subscribers.length !== 0) {

lib$es6$promise$asap$$asap(lib$es6$promise$$internal$$publish, promise);

}

}

function lib$es6$promise$$internal$$reject(promise, reason) {

if (promise._state !== lib$es6$promise$$internal$$PENDING) { return; }

promise._state = lib$es6$promise$$internal$$REJECTED;

promise._result = reason;

lib$es6$promise$asap$$asap(lib$es6$promise$$internal$$publishRejection, promise);

}

function lib$es6$promise$$internal$$subscribe(parent, child, onFulfillment, onRejection) {

var subscribers = parent._subscribers;

var length = subscribers.length;

parent._onerror = null;

subscribers[length] = child;

subscribers[length + lib$es6$promise$$internal$$FULFILLED] = onFulfillment;

subscribers[length + lib$es6$promise$$internal$$REJECTED] = onRejection;

if (length === 0 && parent._state) {

lib$es6$promise$asap$$asap(lib$es6$promise$$internal$$publish, parent);

}

}

function lib$es6$promise$$internal$$publish(promise) {

var subscribers = promise._subscribers;

var settled = promise._state;

if (subscribers.length === 0) { return; }

var child, callback, detail = promise._result;

for (var i = 0; i < subscribers.length; i += 3) {

child = subscribers[i];

callback = subscribers[i + settled];

if (child) {

lib$es6$promise$$internal$$invokeCallback(settled, child, callback, detail);

} else {

callback(detail);

}

}

promise._subscribers.length = 0;

}

function lib$es6$promise$$internal$$ErrorObject() {

this.error = null;

}

var lib$es6$promise$$internal$$TRY_CATCH_ERROR = new lib$es6$promise$$internal$$ErrorObject();

function lib$es6$promise$$internal$$tryCatch(callback, detail) {

try {

return callback(detail);

} catch(e) {

lib$es6$promise$$internal$$TRY_CATCH_ERROR.error = e;

return lib$es6$promise$$internal$$TRY_CATCH_ERROR;

}

}

function lib$es6$promise$$internal$$invokeCallback(settled, promise, callback, detail) {

var hasCallback = lib$es6$promise$utils$$isFunction(callback),

value, error, succeeded, failed;

if (hasCallback) {

value = lib$es6$promise$$internal$$tryCatch(callback, detail);

if (value === lib$es6$promise$$internal$$TRY_CATCH_ERROR) {

failed = true;

error = value.error;

value = null;

} else {

succeeded = true;

}

if (promise === value) {

lib$es6$promise$$internal$$reject(promise, lib$es6$promise$$internal$$cannotReturnOwn());

return;

}

} else {

value = detail;

succeeded = true;

}

if (promise._state !== lib$es6$promise$$internal$$PENDING) {

// noop

} else if (hasCallback && succeeded) {

lib$es6$promise$$internal$$resolve(promise, value);

} else if (failed) {

lib$es6$promise$$internal$$reject(promise, error);

} else if (settled === lib$es6$promise$$internal$$FULFILLED) {

lib$es6$promise$$internal$$fulfill(promise, value);

} else if (settled === lib$es6$promise$$internal$$REJECTED) {

lib$es6$promise$$internal$$reject(promise, value);

}

}

function lib$es6$promise$$internal$$initializePromise(promise, resolver) {

try {

resolver(function resolvePromise(value){

lib$es6$promise$$internal$$resolve(promise, value);

}, function rejectPromise(reason) {

lib$es6$promise$$internal$$reject(promise, reason);

});

} catch(e) {

lib$es6$promise$$internal$$reject(promise, e);

}

}

var lib$es6$promise$$internal$$id = 0;

function lib$es6$promise$$internal$$nextId() {

return lib$es6$promise$$internal$$id++;

}

function lib$es6$promise$$internal$$makePromise(promise) {

promise[lib$es6$promise$$internal$$PROMISE_ID] = lib$es6$promise$$internal$$id++;

promise._state = undefined;

promise._result = undefined;

promise._subscribers = [];

}

function lib$es6$promise$promise$all$$all(entries) {

return new lib$es6$promise$enumerator$$default(this, entries).promise;

}

var lib$es6$promise$promise$all$$default = lib$es6$promise$promise$all$$all;

function lib$es6$promise$promise$race$$race(entries) {

/*jshint validthis:true */

var Constructor = this;

if (!lib$es6$promise$utils$$isArray(entries)) {

return new Constructor(function(resolve, reject) {

reject(new TypeError('You must pass an array to race.'));

});

} else {

return new Constructor(function(resolve, reject) {

var length = entries.length;

for (var i = 0; i < length; i++) {

Constructor.resolve(entries[i]).then(resolve, reject);

}

});

}

}

var lib$es6$promise$promise$race$$default = lib$es6$promise$promise$race$$race;

function lib$es6$promise$promise$reject$$reject(reason) {

/*jshint validthis:true */

var Constructor = this;

var promise = new Constructor(lib$es6$promise$$internal$$noop);

lib$es6$promise$$internal$$reject(promise, reason);

return promise;

}

var lib$es6$promise$promise$reject$$default = lib$es6$promise$promise$reject$$reject;

function lib$es6$promise$promise$$needsResolver() {

throw new TypeError('You must pass a resolver function as the first argument to the promise constructor');

}

function lib$es6$promise$promise$$needsNew() {

throw new TypeError("Failed to construct 'Promise': Please use the 'new' operator, this object constructor cannot be called as a function.");

}

var lib$es6$promise$promise$$default = lib$es6$promise$promise$$Promise;

/**

Promise objects represent the eventual result of an asynchronous operation. The

primary way of interacting with a promise is through its `then` method, which

registers callbacks to receive either a promise's eventual value or the reason

why the promise cannot be fulfilled.

Terminology

-----------

- `promise` is an object or function with a `then` method whose behavior conforms to this specification.

- `thenable` is an object or function that defines a `then` method.

- `value` is any legal JavaScript value (including undefined, a thenable, or a promise).

- `exception` is a value that is thrown using the throw statement.

- `reason` is a value that indicates why a promise was rejected.

- `settled` the final resting state of a promise, fulfilled or rejected.

A promise can be in one of three states: pending, fulfilled, or rejected.

Promises that are fulfilled have a fulfillment value and are in the fulfilled

state. Promises that are rejected have a rejection reason and are in the

rejected state. A fulfillment value is never a thenable.

Promises can also be said to *resolve* a value. If this value is also a

promise, then the original promise's settled state will match the value's

settled state. So a promise that *resolves* a promise that rejects will

itself reject, and a promise that *resolves* a promise that fulfills will

itself fulfill.

Basic Usage:

------------

```js

var promise = new Promise(function(resolve, reject) {

// on success

resolve(value);

// on failure

reject(reason);

});

promise.then(function(value) {

// on fulfillment

}, function(reason) {

// on rejection

});

```

Advanced Usage:

---------------

Promises shine when abstracting away asynchronous interactions such as

`XMLHttpRequest`s.

```js

function getJSON(url) {

return new Promise(function(resolve, reject){

var xhr = new XMLHttpRequest();

xhr.open('GET', url);

xhr.onreadystatechange = handler;

xhr.responseType = 'json';

xhr.setRequestHeader('Accept', 'application/json');

xhr.send();

function handler() {

if (this.readyState === this.DONE) {

if (this.status === 200) {

resolve(this.response);

} else {

reject(new Error('getJSON: `' + url + '` failed with status: [' + this.status + ']'));

}

}

};

});

}

getJSON('/posts.json').then(function(json) {

// on fulfillment

}, function(reason) {

// on rejection

});

```

Unlike callbacks, promises are great composable primitives.

```js

Promise.all([

getJSON('/posts'),

getJSON('/comments')

]).then(function(values){

values[0] // => postsJSON

values[1] // => commentsJSON

return values;

});

```

@class Promise

@param {function} resolver

Useful for tooling.

@constructor

*/

function lib$es6$promise$promise$$Promise(resolver) {

this[lib$es6$promise$$internal$$PROMISE_ID] = lib$es6$promise$$internal$$nextId();

this._result = this._state = undefined;

this._subscribers = [];

if (lib$es6$promise$$internal$$noop !== resolver) {

typeof resolver !== 'function' && lib$es6$promise$promise$$needsResolver();

this instanceof lib$es6$promise$promise$$Promise ? lib$es6$promise$$internal$$initializePromise(this, resolver) : lib$es6$promise$promise$$needsNew();

}

}

lib$es6$promise$promise$$Promise.all = lib$es6$promise$promise$all$$default;

lib$es6$promise$promise$$Promise.race = lib$es6$promise$promise$race$$default;

lib$es6$promise$promise$$Promise.resolve = lib$es6$promise$promise$resolve$$default;

lib$es6$promise$promise$$Promise.reject = lib$es6$promise$promise$reject$$default;

lib$es6$promise$promise$$Promise._setScheduler = lib$es6$promise$asap$$setScheduler;

lib$es6$promise$promise$$Promise._setAsap = lib$es6$promise$asap$$setAsap;

lib$es6$promise$promise$$Promise._asap = lib$es6$promise$asap$$asap;

lib$es6$promise$promise$$Promise.prototype = {

constructor: lib$es6$promise$promise$$Promise,

/**

The primary way of interacting with a promise is through its `then` method,

which registers callbacks to receive either a promise's eventual value or the

reason why the promise cannot be fulfilled.

```js

findUser().then(function(user){

// user is available

}, function(reason){

// user is unavailable, and you are given the reason why

});

```

Chaining

--------

The return value of `then` is itself a promise. This second, 'downstream'

promise is resolved with the return value of the first promise's fulfillment

or rejection handler, or rejected if the handler throws an exception.

```js

findUser().then(function (user) {

return user.name;

}, function (reason) {

return 'default name';

}).then(function (userName) {

// If `findUser` fulfilled, `userName` will be the user's name, otherwise it

// will be `'default name'`

});

findUser().then(function (user) {

throw new Error('Found user, but still unhappy');

}, function (reason) {

throw new Error('`findUser` rejected and we're unhappy');

}).then(function (value) {

// never reached

}, function (reason) {

// if `findUser` fulfilled, `reason` will be 'Found user, but still unhappy'.

// If `findUser` rejected, `reason` will be '`findUser` rejected and we're unhappy'.

});

```

If the downstream promise does not specify a rejection handler, rejection reasons will be propagated further downstream.

```js

findUser().then(function (user) {

throw new PedagogicalException('Upstream error');

}).then(function (value) {

// never reached

}).then(function (value) {

// never reached

}, function (reason) {

// The `PedgagocialException` is propagated all the way down to here

});

```

Assimilation

------------

Sometimes the value you want to propagate to a downstream promise can only be

retrieved asynchronously. This can be achieved by returning a promise in the

fulfillment or rejection handler. The downstream promise will then be pending

until the returned promise is settled. This is called *assimilation*.

```js

findUser().then(function (user) {

return findCommentsByAuthor(user);

}).then(function (comments) {

// The user's comments are now available

});

```

If the assimliated promise rejects, then the downstream promise will also reject.

```js

findUser().then(function (user) {

return findCommentsByAuthor(user);

}).then(function (comments) {

// If `findCommentsByAuthor` fulfills, we'll have the value here

}, function (reason) {

// If `findCommentsByAuthor` rejects, we'll have the reason here

});

```

Simple Example

--------------

Synchronous Example

```javascript

var result;

try {

result = findResult();

// success

} catch(reason) {

// failure

}

```

Errback Example

```js

findResult(function(result, err){

if (err) {

// failure

} else {

// success

}

});

```

Promise Example;

```javascript

findResult().then(function(result){

// success

}, function(reason){

// failure

});

```

Advanced Example

--------------

Synchronous Example

```javascript

var author, books;

try {

author = findAuthor();

books = findBooksByAuthor(author);

// success

} catch(reason) {

// failure

}

```

Errback Example

```js

function foundBooks(books) {

}

function failure(reason) {

}

findAuthor(function(author, err){

if (err) {

failure(err);

// failure

} else {

try {

findBoooksByAuthor(author, function(books, err) {

if (err) {

failure(err);

} else {

try {

foundBooks(books);

} catch(reason) {

failure(reason);

}

}

});

} catch(error) {

failure(err);

}

// success

}

});

```

Promise Example;

```javascript

findAuthor().

then(findBooksByAuthor).

then(function(books){

// found books

}).catch(function(reason){

// something went wrong

});

```

@method then

@param {Function} onFulfilled

@param {Function} onRejected

Useful for tooling.

@return {Promise}

*/

then: lib$es6$promise$then$$default,

/**

`catch` is simply sugar for `then(undefined, onRejection)` which makes it the same

as the catch block of a try/catch statement.

```js

function findAuthor(){

throw new Error('couldn't find that author');

}

// synchronous

try {

findAuthor();

} catch(reason) {

// something went wrong

}

// async with promises

findAuthor().catch(function(reason){

// something went wrong

});

```

@method catch

@param {Function} onRejection

Useful for tooling.

@return {Promise}

*/

'catch': function(onRejection) {

return this.then(null, onRejection);

}

};

var lib$es6$promise$enumerator$$default = lib$es6$promise$enumerator$$Enumerator;

function lib$es6$promise$enumerator$$Enumerator(Constructor, input) {

this._instanceConstructor = Constructor;

this.promise = new Constructor(lib$es6$promise$$internal$$noop);

if (!this.promise[lib$es6$promise$$internal$$PROMISE_ID]) {

lib$es6$promise$$internal$$makePromise(this.promise);

}

if (lib$es6$promise$utils$$isArray(input)) {

this._input = input;

this.length = input.length;

this._remaining = input.length;

this._result = new Array(this.length);

if (this.length === 0) {

lib$es6$promise$$internal$$fulfill(this.promise, this._result);

} else {

this.length = this.length || 0;

this._enumerate();

if (this._remaining === 0) {

lib$es6$promise$$internal$$fulfill(this.promise, this._result);

}

}

} else {

lib$es6$promise$$internal$$reject(this.promise, lib$es6$promise$enumerator$$validationError());

}

}

function lib$es6$promise$enumerator$$validationError() {

return new Error('Array Methods must be provided an Array');

}

lib$es6$promise$enumerator$$Enumerator.prototype._enumerate = function() {

var length = this.length;

var input = this._input;

for (var i = 0; this._state === lib$es6$promise$$internal$$PENDING && i < length; i++) {

this._eachEntry(input[i], i);

}

};

lib$es6$promise$enumerator$$Enumerator.prototype._eachEntry = function(entry, i) {

var c = this._instanceConstructor;

var resolve = c.resolve;

if (resolve === lib$es6$promise$promise$resolve$$default) {

var then = lib$es6$promise$$internal$$getThen(entry);

if (then === lib$es6$promise$then$$default &&

entry._state !== lib$es6$promise$$internal$$PENDING) {

this._settledAt(entry._state, i, entry._result);

} else if (typeof then !== 'function') {

this._remaining--;

this._result[i] = entry;

} else if (c === lib$es6$promise$promise$$default) {

var promise = new c(lib$es6$promise$$internal$$noop);

lib$es6$promise$$internal$$handleMaybeThenable(promise, entry, then);

this._willSettleAt(promise, i);

} else {

this._willSettleAt(new c(function(resolve) { resolve(entry); }), i);

}

} else {

this._willSettleAt(resolve(entry), i);

}

};

lib$es6$promise$enumerator$$Enumerator.prototype._settledAt = function(state, i, value) {

var promise = this.promise;

if (promise._state === lib$es6$promise$$internal$$PENDING) {

this._remaining--;

if (state === lib$es6$promise$$internal$$REJECTED) {

lib$es6$promise$$internal$$reject(promise, value);

} else {

this._result[i] = value;

}

}

if (this._remaining === 0) {

lib$es6$promise$$internal$$fulfill(promise, this._result);

}

};

lib$es6$promise$enumerator$$Enumerator.prototype._willSettleAt = function(promise, i) {

var enumerator = this;

lib$es6$promise$$internal$$subscribe(promise, undefined, function(value) {

enumerator._settledAt(lib$es6$promise$$internal$$FULFILLED, i, value);

}, function(reason) {

enumerator._settledAt(lib$es6$promise$$internal$$REJECTED, i, reason);

});

};

function lib$es6$promise$polyfill$$polyfill() {

var local;

if (typeof global !== 'undefined') {

local = global;

} else if (typeof self !== 'undefined') {

local = self;

} else {

try {

local = Function('return this')();

} catch (e) {

throw new Error('polyfill failed because global object is unavailable in this environment');

}

}

var P = local.Promise;

if (P && Object.prototype.toString.call(P.resolve()) === '[object Promise]' && !P.cast) {

return;

}

local.Promise = lib$es6$promise$promise$$default;

}

var lib$es6$promise$polyfill$$default = lib$es6$promise$polyfill$$polyfill;

lib$es6$promise$promise$$default.Promise = lib$es6$promise$promise$$default;

lib$es6$promise$promise$$default.polyfill = lib$es6$promise$polyfill$$default;

/* global define:true module:true window: true */

if (typeof define === 'function' && define['amd']) {

define(function() { return lib$es6$promise$promise$$default; });

} else if (typeof module !== 'undefined' && module['exports']) {

module['exports'] = lib$es6$promise$promise$$default;

} else if (typeof this !== 'undefined') {

this['Promise'] = lib$es6$promise$promise$$default;

}

lib$es6$promise$polyfill$$default();

}).call(this);

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值