使用fetch遇到过的坑

来源:互联网 发布:老虎机控制器软件下载 编辑:程序博客网 时间:2024/06/06 02:33

前段时间在项目中用到了这个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 只需改两处:

  



  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
原创粉丝点击