首页 > 解决方案 > 如何避免 UI5 中的“主线程上的同步 XMLHttpRequest”警告?

问题描述

我用以下引导程序盯着我的 UI5 index.js

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 文档

静态依赖加载在sap.ui.define调用的依赖声明数组中。这些依赖项总是在执行定义的模块之前预先加载。

我是否正确理解在这种情况下,模块将始终以同步方式加载,并且没有真正的方法可以避免“主线程上的同步 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 sample进行了深入探索后,我找到了sync XHR警告的原因。那是"description": "{{appDescription}}"并且"title": "{{appTitle}}"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!"

用静态值替换它后,警告就消失了。

标签: javascriptasynchronousasync-awaitxmlhttprequestsapui5

解决方案


UI5 的早期开发主要基于同步 XHR。旧版应用程序或某些过时的文档主题可能仍引用默认禁用异步选项根本没有异步选项的 API,例如:sap.ui.controller, sap.ui.component, sap.ui.*fragment, sap.ui.*view, jQuery.sap.require, sap.ui.requireSync,以及问题中提到jQuery.sap.sjax的构造函数。ComponentContainer

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

  1. 遵循记录在案的指南:

    特别是在引导时,请使用该data-sap-ui-async="true"选项,如果应用程序有Component.js请使用声明性sap/ui/core/ComponentSupport模块data-sap-ui-oninitsap.ui.core.ComponentContainer而不是手动实例化。例如:

    <head>
      <!-- ... -->
      <script id="sap-ui-bootstrap" ...
        data-sap-ui-async="true"
        data-sap-ui-oninit="module:sap/ui/core/ComponentSupport"
      ></script>
    </head>
    <body id="content" class="sapUiBody">
      <div data-sap-ui-component
        data-id="rootComponentContainer"
        data-name="demo"
        data-settings='{ "id": "rootComponent" }'
        ...
      ></div>
    </body>

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

  1. xx-nosync使用引导选项运行应用程序。例如,在 URL 中:

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

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

    • 如果应用程序使用v2.ODataModel,它可能会抱怨模块sap/ui/thirdparty/datajs是同步加载的。在这种情况下,将以下内容添加到引导配置中:
      <script id="sap-ui-bootstrap" ...
        data-sap-ui-async="true"
        data-sap-ui-oninit="module:sap/ui/core/ComponentSupport"
        data-sap-ui-modules="sap/ui/thirdparty/datajs"
      ></script>
    • 如果 aResourceModel是在 JS 中手动创建的,请确保在async此处启用该标志:
      const i18nModel = new ResourceModel({ // required by "sap/ui/model/resource/ResourceModel"
        bundleName: "demo.i18n.i18n",
        supportedLocales: [""],
        fallbackLocale: "",
        async: true, // <--
      });
      i18nModel.getResourceBundle().then(resourceBundle => {
        this.getOwnerComponent().setModel(i18nModel, "i18n");
        resourceBundle.getText(/*...*/); // See sap/base/i18n/ResourceBundle
      });

    检查报告的 API 的 API 参考。大多数情况下,它们要么已被弃用,要么带有默认async设置的标志。false

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

  • 实例化时使用同步 XHR 获取的CLDR 文件sap/ui/core/LocaleData(用于例如 Calendar 或 DatePicker。请参阅问题 #2345)。
  • 当解析 i18n Handlebar-like "{{...}}"-syntax inmanifest.json

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


回答这个问题:如果配置设置为(Replaces )sap.ui.definesap.ui.require异步加载依赖项。还要确保向 中添加依赖库,以防止出现主要的性能瓶颈。data-sap-ui-asynctrue data-sap-ui-preload="async"manifest.json

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

new ComponentContainer({
  height: "100%",
  name: "webapp",
  async: true, // or
  manifest: true, // sets the `async` option automatically to true
})

推荐阅读