如何避免 UI5 中的 "Synchronous XMLHttpRequest on the main thread" 警告?

How to avoid "Synchronous XMLHttpRequest on the main thread" warning in UI5?

我正在用 index.js 中的以下引导启动我的 UI5:

sap.ui.define([
    "sap/m/Shell",
    "sap/ui/core/ComponentContainer"
], (Core, Shell, ComponentContainer) => {
    "use strict";

    new Shell("", {
        app: new ComponentContainer("", {
            height: "100%",
            name: "webapp"
        }),
        appWidthLimited: false
    }).placeAt("content");
});

根据 UI5 documentation:

Static dependencies are loaded in the dependency declaration array of the sap.ui.define call. These dependencies are always loaded in advance before executing the defined module.

我的理解是否正确,在这种情况下,模块将始终以同步方式加载,并且没有真正的方法来避免 «主线程上的同步 XMLHttpRequest» 警告?

也许我可以将 new sap.m.Shell(sId?, mSettings?) 换成 async/await 吗?

更新 #1:

我用 ?sap-ui-xx-nosync=warn 检查了加载并得到了以下结果:

出于某种原因 i18n/i18n_en.properties 被同步加载。我访问 i18n 的唯一地方是:

const oBundle = myI18nModel.getResourceBundle();

但是按照文档,我无法理解为什么myI18nModel.getResourceBundle()会导致同步加载。

更新#2:

在深入研究 no sync XHR 示例后,我找到了 sync XHR 警告的原因。那是 "description": "{{appDescription}}""title": "{{appTitle}}" in manifest.json 明确指出:

"title": "Here the i18n bundles can't be loaded with 'async: true' yet!",
"description": "Same here. Hence, no 'i18n' in this 'sap.app' section!"

用静态值替换后警告消失。

控制台中的同步 XMLHttpRequest 警告可能来自实际核心的剩余部分。我知道启动板在这方面存在一些问题。如果您计时或仔细查看您的网络选项卡/源选项卡,您会发现在加载您自己的代码之前会显示该消息。

在像 sap.jquery.js 这样的文件中的某处或类似的行中,您会发现 XMLHtppRequests 设置了 sync 标志。我已经与 UI5 团队就此进行了对话,并考虑将其移除,但未提供时间表。

为了更直接地回答您的问题,require 部分是异步的。这个想法取自 require js,现在至少已有 10 年历史了。

// 编辑

async/await 不会做任何事情,因为 none 是基于承诺的。执行 sap.m.Shell 只是假设 window 对象在控制器加载之前附加了 sap.m 库,例如,您可以确保通过清单预加载。

UI5 的早期开发很大程度上基于 synchronous XHRs。遗留应用程序或一些过时的文档主题可能仍然引用 APIs,它们默认禁用 异步选项 没有异步选项 完全如:sap.ui.controllersap.ui.componentsap.ui.*fragmentsap.ui.*viewjQuery.sap.requiresap.ui.requireSyncjQuery.sap.sjax 和构造函数问题中提到的 ComponentContainer 的功能。

为了减少同步 XHR 调用的次数:

  1. 遵循记录的指南:

    特别是当 bootstrapping 时,使用 data-sap-ui-async="true" 选项,并且,如果应用程序有 Component.jsuse the declarative sap/ui/core/ComponentSupport module in data-sap-ui-oninit 而不是手动实例化 sap.ui.core.ComponentContainer .例如:

    <头>
      <!-- ... -->
      <脚本 ID="sap-ui-bootstrap" ...
        data-sap-ui-async="true"
        <strong>data-sap-ui-oninit="module:sap/ui/core/ComponentSupport"</strong>
      ></脚本>
    </头>
    <正文 ID="content" class="sapUiBody">
      <div data-sap-ui-component
        data-id="rootComponentContainer"
        data-name="demo"
        data-settings='{ "id": "rootComponent" }'
        ...
      ></div>
    </body>
    

    这会自动创建一个 ComponentContainer,将其推送到 DOM,并异步加载 Component.jsmanifest.json 完全同时避免内联脚本或单独的 bootstrap 脚本。

  1. 运行 带有 xx-nosync bootstrap option 的应用程序。例如,在 URL:

    https://<host>/my/awesome/app/?<strong>sap-ui-xx-nosync=警告</strong>
    

    UI5 将在浏览器控制台中记录 “正在使用同步 XHR 加载” 同步获取的每个文件(忽略其他 [nosync] 消息)。例如:

    • 如果应用程序使用 v2.ODataModel,它可能会抱怨模块 sap/ui/thirdparty/datajs 是同步加载的。在这种情况下,将以下内容添加到 bootstrap 配置中:
      <脚本 ID="sap-ui-bootstrap" ...
        data-sap-ui-async="true"
        data-sap-ui-oninit="module:sap/ui/core/ComponentSupport"
        <strong>data-sap-ui-modules="sap/ui/thirdparty/datajs"</strong>
      ></script>
      
    • 如果在 JS 中手动创建 ResourceModel,请确保在那里启用 async 标志:
      const i18nModel = new ResourceModel({ // "sap/ui/model/resource/ResourceModel" 要求
        bundleName: "demo.i18n.i18n",
        支持的语言环境:[“”],
        fallbackLocale:“”,
        <strong>异步:真</strong>, // <--
      });
      i18nModel.getResourceBundle().then(resourceBundle => {
        this.getOwnerComponent().setModel(i18nModel, "i18n");
        resourceBundle.getText(/*...*/); // 见 sap/base/i18n/ResourceBundle
      });
      

    检查报告的 API 的 API 引用。大多数时候,它们要么被弃用,要么带有默认设置为 falseasync 标志。

还有一些 API 还没有异步替换 例如:

  • CLDR file being fetched with sync XHR when instantiating sap/ui/core/LocaleData (Used in e.g. Calendar or DatePicker. See Issue #2345).
  • 解析 i18n 时 Handlebar-like "{{...}}"-manifest.json
  • 中的语法

使用最新的稳定版UI5,可以消除大部分同步请求。
这是一个没有同步 XHR 的 样本:https://embed.plnkr.co/7txzTsNwOBDbyi87


回答问题:sap.ui.definesap.ui.require 异步加载依赖项 如果 data-sap-ui-async 配置设置为 true . Also make sure to 以防止出现主要的性能瓶颈。

async-await/Promise 包装同步内容请求不会有帮助。最好寻找异步替代方案。例如,ComponentContainer 在构造函数设置中有一个 async 标志,如果启用,它会异步获取 Component.jsmanifest.json 文件:

新组件容器({
  高度:“100%”,
  姓名:"webapp",
  <strong>异步:真,//或
  manifest: true, // 将 `async` 选项自动设置为 true</strong>
})