为啥我的 Vue 项目中的 promise.finally 不能在 Edge 中运行?

Posted

技术标签:

【中文标题】为啥我的 Vue 项目中的 promise.finally 不能在 Edge 中运行?【英文标题】:Why is promise.finally in my Vue project not working in Edge?为什么我的 Vue 项目中的 promise.finally 不能在 Edge 中运行? 【发布时间】:2020-05-14 07:11:18 【问题描述】:

我在让我的 polyfill 在 Edge 中工作时遇到了巨大的麻烦。我试图按照文档进行各种尝试,但都不起作用。这似乎是promise.finally,具体来说这是行不通的。这发生在 vuex 模块中,所以我尝试将 vuex 添加到 vue.config 中的 transpileDependencies 但没有运气。

我的 babel.config.js:

module.exports = 
  presets: [['@vue/cli-plugin-babel/preset', 
    useBuiltIns: 'entry',
  ]],
;

在我的 main.js 中,我在最顶部有以下两个导入:

import 'core-js/stable';
import 'regenerator-runtime/runtime';

我的 vue.config.js

// eslint-disable-next-line import/no-extraneous-dependencies
const webpack = require('webpack');

const isProd = process.env.NODE_ENV === 'production';

module.exports = 
  configureWebpack: 
    // Set up all the aliases we use in our app.
    plugins: [
      new webpack.optimize.LimitChunkCountPlugin(
        maxChunks: 6,
      ),
    ],
  ,
  css: 
    // Enable CSS source maps.
    sourceMap: !isProd,
  ,
  transpileDependencies: ['vuex'],
;

请注意,如上所述,我尝试了使用和不使用 transpileDepedencies。它在这里说 vue/babel-preset-app es7.promise.finally 作为默认 polyfill 包含在内

版本:

Microsoft Edge:44.18 Microsoft Edgehtml 18.18362 @vue/cli-plugin-babel": "^4.1.2" “core-js”:“^3.6.4” “再生器运行时”:“^0.13.3”

13/02 更新

所以我尝试在我的网站上的边缘键入 Promise.prototype,它确实显示为 polyfill:

所以目前我正在调查我的链(axios/vue axios)的某些部分是否没有返回承诺。由于它在 chrome 中工作,我怀疑链的一部分没有正确填充?

这是我的整个链条:

/* VUEX MODULE ACTION */  
[a.ALL_CUSTOMERS](context) 
    context.commit(m.SET_CUSTOMER_LOADING, true);
    CustomerService.getAll()
      .then(( data ) => 
        context.commit(m.SET_CUSTOMERS, data);
      )
      .finally(() => context.commit(m.SET_CUSTOMER_LOADING, false));
  ,

/* CUSTOMER SERVICE */
import ApiService from '@/common/api.service';
const CustomerService = 
  getAll() 
    const resource = 'customers/';
    return ApiService.get(resource);
  ,
...


/* API SERVICE */
import Vue from 'vue';
import axios from 'axios';
import VueAxios from 'vue-axios';

const ApiService = 
  init() 
    Vue.use(VueAxios, axios);
    let baseUrl = process.env.VUE_APP_APIURL;
    Vue.axios.defaults.baseURL = baseUrl;
  ,

  setHeader() 
    Vue.axios.defaults.headers.common.Authorization = `Bearer $getToken()`;
  ,

  get(resource) 
    this.setHeader();
    return Vue.axios.get(`$resource`);
  ,
  ...

【问题讨论】:

有趣,Edge 不需要 polyfill,因为它支持 finally() on Promise 从 v18 开始 出于好奇,EdgeHTML 版本是什么?您可以在 Edge 版本的下方找到它。我问是因为 CanIUse 支持这一点。从他们的网站:*Version number used for Edge is based on the number of EdgeHTML rather than Edge itself. This is because EdgeHTML is the engine for Edge that is related to feature support change. Microsoft EdgeHTML 18.18362 Edge 应该告诉你这是一个承诺。而是说它是一个对象。所以返回的对象不是预期的承诺。 这个问题可以通过提供一个简化的 repo 来重现问题,以便其他人可以提供帮助。像codesandbox.io 这样的网站可以用于此目的。 【参考方案1】:

我以前也遇到过这个问题。 只是最后没有在Edge上工作。 我终于像下面的 VVV 一样进行了更新,并且成功了。

除了下面详述的行为之外,这应该处理 thenable 的 species 的传播:

Promise.prototype.finally = Promise.prototype.finally || 
  finally (fn) 
    const onFinally = value => Promise.resolve(fn()).then(() => value);
    return this.then(
      result => onFinally(result),
      reason => onFinally(Promise.reject(reason))
    );
  
.finally;

此实现基于 finally() 的记录行为,并取决于 then() 是否符合规范:

finally 回调不会接收任何参数,因为没有 确定承诺是否已履行或 被拒绝。这个用例正是在你不关心的时候 拒绝原因,或者履行价值,所以没有必要 提供它。

不同于Promise.resolve(2).then(() => , () => )(它将是 用未定义解决),Promise.resolve(2).finally(() => ) 将是 用 2 解决。

同样,不像Promise.reject(3).then(() => , () => )( 将用 undefined 实现),Promise.reject(3).finally(() => ) 将被 3 拒绝。

注意:finally 中的抛出(或返回被拒绝的承诺) 回调将拒绝带有拒绝原因的新承诺 调用 throw() 时指定。

【讨论】:

【参考方案2】:

这是core-js 中的一个已知问题。

理论上,Edge 为 finally 提供了一个 Promise polyfill,但功能检测或您的浏览器列表可能出现问题,您需要提供一个 polyfill :shrug:

我会从你的项目中删除 Vue babel 插件和 core-js,然后 npm 重新安装它们。

npm install @vue/cli-plugin-babel --save-dev

npm install core-js --save

另外,请确保您通过配置 (babel.config.js) here使用 core-js@3

最后,关于在您的 vuex 商店中执行的其他 3rd 方库,有一些关于 polyfill + Promises 的 Github 问题。将所有这三个库(axios、vue-axios、vuex)添加到您的transpileDependencies 部分。如果解决了问题,请开始删除依赖项以查看是否需要它们。

【讨论】:

不幸的是尝试了你所有的建议,结果相同:( 很奇怪。第三方插件是否最终删除了 Promise.finally? 抱歉回答迟了。如何判断第三方插件是否删除了它?【参考方案3】:

尝试将.browserslistrc 文件添加到您的项目根目录,内容如下:

> 1%
last 2 versions

查看https://github.com/browserslist/browserslist#best-practiceslast versions 配置信息。


如果这不能解决缺少的 poly-fill,请尝试禁用您正在使用的限制块数量的插件,以确保这不会导致任何 poly-fill 被忽略。

plugins: [
  new webpack.optimize.LimitChunkCountPlugin(
    maxChunks: 6,
  ),
],

【讨论】:

我已经有了你列出的版本的 browserslistrc。刚刚在没有插件的情况下进行了测试 - 没有效果:( 我的 babel 插件文件只有:module.exports = presets: [ '@vue/cli-plugin-babel/preset' ] 你的 promise.finally 在边缘工作?您是否可以分享您的软件包列表和配置,以便我可以尝试推断是哪个软件包导致了问题? 我总是使用 cli.vuejs.org/guide/creating-a-project.html#vue-create 创建我的项目,但 Edge 18+ 支持 finally() 不需要 poly-fill,只适用于 Internet Explorer? 您的问题可能来自您正在使用的 ApiService,它可能不会返回本机 Promise,而是自己创建的模拟 Promise。尝试直接使用 axios 设置相同的调用作为测试。

以上是关于为啥我的 Vue 项目中的 promise.finally 不能在 Edge 中运行?的主要内容,如果未能解决你的问题,请参考以下文章

为啥 vue-router 不起作用?我的项目在 GitHub

为啥从Vue.js中的列表中删除项目时移动转换需要绝对位置

为啥我的过渡不适用于 Bootstrap-vue 中的警报 v-model?

为啥不在 Vue 和 Vue Router 生产环境中渲染我的组件?

为啥idea中的vue用不了new vue的格式

为啥我的 Vue 应用程序中的 v-model 输入会在更改时触发突变错误?