在使用polyfill的IE11中,Promise.catch失败

itt*_*elo 5 javascript polyfills internet-explorer-11 polymer es6-promise

我在我的Polymer 2项目中使用ES6,Promises和fetch.因为我需要支持至少IE11,我正在使用Babel(通过聚合物构建)和使用polyfills.io来进行polyfill fetch和Promise支持.我的polyfills.io导入发生在任何其他导入之前,如下所示:

<script src="https://cdn.polyfill.io/v2/polyfill.js?features=default,fetch&flags=gated"></script>

当我加载页面时,IE11控制台中出现此错误:

SCRIPT438: Object doesn't support property or method 'catch'

查看我的代码,我唯一一次使用catch是在Promises中.例如:

loadSchemas() {
  return APP.client
    .search("+type:Schema")
    .then(result => {
      // Do things with results.
    })
    .catch(error => {
      // Deal with errors.
    });
}
Run Code Online (Sandbox Code Playgroud)

如果我删除了catch,页面加载没有错误,但显然它没有运行我的错误处理代码.

为什么这不按预期工作?它在Firefox,Chrome和Safari中运行良好.我尝试了许多不同的承诺polyfills并仍然得到相同的错误,所以我不认为这是一个polyfill bug.

itt*_*elo 5

因此,看起来 catch 是 IE 9+ 中的保留字。我在https://github.com/lahmatiy/es6-promise-polyfill找到了这个信息块:

catch是 IE<9 中的保留字,意思是promise.catch(func)抛出语法错误。要解决此问题,请使用字符串访问该属性:

promise['catch'](function(err) { // ... });

或者.then改用:

promise.then(undefined, function(err) { // ... });

如果我修改它以避免捕获,我的代码可以在 IE11 中工作,如下所示:

loadSchemas() {
  return APP.client
    .search("+type:Schema")
    .then(result => {
      // Do things with results.
    }, error => {
      // Deal with errors.
    });
}
Run Code Online (Sandbox Code Playgroud)


Jea*_*émi 1

实际上,如果您导入 /webcomponentsjs/webcomponents-lite.js polyfill(使用 Polymer 2.x),它很可能会重写 Promise polyfill。这个polyfill目前有一个关于“catch”的未决问题:

https://github.com/webcomponents/webcomponentsjs/issues/837

建议的解决方法是:

将 WebComponents polyfill 的版本固定为 1.0.7 或更低。

我查看了 Promise 的 webcomponents-lite polyfill,如果以下内容为 false,它们会替换 Promise 定义(我简化了编写):

Object.prototype.toString.call(window.Promise.resolve()) == "[object Promise]"
Run Code Online (Sandbox Code Playgroud)

但是,即使您从其他来源导入 Promise polyfill,它们也会呈现为"[object Object]",因此它们会被替换。

注意:Promise 的 webcomponents-lite polyfill 目前也没有公开Promise.all()方法,这也可能是由于 Closure 编译器的上述问题造成的。

此问题未解决时建议的解决方法:

在 Webcomponents polyfill 之后加载您的 polyfill。

// load webcomponents polyfills
(function() {
    if ('registerElement' in document
        && 'import' in document.createElement('link')
        && 'content' in document.createElement('template')) {
        // browser has web components
    }
    else {
        // polyfill web components
        let e = document.createElement('script');
        e.src = '/bower_components/webcomponentsjs/webcomponents-lite.js';
        document.head.appendChild(e);
    }

    // Promise polyfill for IE11, as of 2017/09/07 webcomponents Promise polyfill is broken
    // (https://github.com/webcomponents/webcomponentsjs/issues/837)
    if (!window['Promise'] || !window['Promise']['reject']){
        // Remove the webcomponents polyfilled Promise object
        delete window.Promise;

        // Add own polyfill for Promise
        let e = document.createElement('script');
        e.src = '/lib/promisePolyfill/promise.js'; // or polyfill.io
        document.head.appendChild(e);
    }
})();
Run Code Online (Sandbox Code Playgroud)