【问题标题】:Promise.catch fails in IE11 with polyfillsPromise.catch 在 IE11 中使用 polyfill 失败
【发布时间】:2017-08-29 17:44:03
【问题描述】:

我在我的 Polymer 2 项目中使用 ES6、Promises 和 fetch。因为我需要至少支持 IE11,所以我正在使用 Babel 进行编译(通过 polymer-build)并使用 polyfills.io 来填充 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.
    });
}

如果我删除了捕获,页面加载时不会出现错误,但它显然没有运行我的错误处理代码。

为什么没有按预期工作?它在 Firefox、Chrome 和 Safari 中运行良好。我尝试了许多不同的 Promise polyfill,但仍然出现相同的错误,所以我认为这不是 polyfill 错误。

【问题讨论】:

    标签: javascript polymer internet-explorer-11 es6-promise polyfills


    【解决方案1】:

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

    catch是IEpromise.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.
        });
    }
    

    【讨论】:

    • 这似乎不是最理想的。我希望 Babel 会为你解决这个问题。可能 Babel 中存在错误或配置问题。
    【解决方案2】:

    实际上,如果你导入 /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,如果以下错误,它们会替换 Promise 定义(我简化了写作):

    Object.prototype.toString.call(window.Promise.resolve()) == "[object Promise]"
    

    但是,即使您从其他来源导入 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);
        }
    })();
    

    【讨论】:

    • 不幸的是,我需要更新版本的 WebComponents polyfill 来修复其他错误,因此固定到 1.0.7 对我不起作用。很高兴知道这实际上是一个将(希望)修复的错误。
    • 确实!最后我自己的解决方法是在 WebComponents polyfill 之后加载(如果需要)Promise polyfill。要检测是否需要它,只需检查“reject”属性是否存在: if (!window['Promise'] || !window['Promise']['reject']) { /* Load polyfill */ }跨度>
    • 对我来说,我尝试过的任何方法都无法解决问题... :-( 怎么会???
    • WebComponent 问题现已关闭并合并 (github.com/webcomponents/webcomponentsjs/issues/837),因此下一个版本的 webcomponentsjs 应该可以工作。
    • 我已经确认 catch 现在可以与最近发布的 1.0.11 的 webcomponentsjs 一起使用。我现在按预期在 IE11 上工作。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-03-23
    • 2020-05-07
    • 1970-01-01
    • 2020-01-17
    • 1970-01-01
    • 2017-12-30
    • 1970-01-01
    相关资源
    最近更新 更多