如何避免“主线程上的同步XMLHttpRequest"?UI5中警告? [英] How to avoid "Synchronous XMLHttpRequest on the main thread" warning in UI5?

查看:159
本文介绍了如何避免“主线程上的同步XMLHttpRequest"?UI5中警告?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

  sap.ui.define(["sap/m/Shell","sap/ui/core/ComponentContainer"],(Core,Shell,ComponentContainer)=>{严格使用";新的Shell(,",{应用程序:new ComponentContainer(",{高度:"100%",名称:"webapp"}),appWidthLimited:否}).placeAt("content");}); 

根据示例后,我发现了同步XHR 警告.那是 manifest中的"description":"{{appDescription}}" "title":"{{appTitle}}" .json ,其中明确指出:

 "title":此处无法使用'async:true'加载i18n捆绑包!",描述":此处相同."因此,在此"sap.app"部分中没有"i18n"!" 

将其替换为静态值后,警告消失了.

解决方案

UI5的早期开发很大程度上基于性能检查表

  • 您的应用程序是否已准备好异步加载?
  • 尤其是在引导时,请使用 data-sap-ui-async ="true" 选项,如果应用程序具有 Component.js ,则 使用 sap/ui/core/ComponentSupport 中的声明性模块> data-sap-ui-oninit ,而不是手动实例化 sap.ui.core.ComponentContainer .例如:

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

    这会自动创建一个 ComponentContainer ,将其推送到DOM,并异步地加载 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>  

      • 如果 ResourceModel 是在JS中手动创建的,请确保在其中启用 async 标志:

          const i18nModel = new ResourceModel({//"sap/ui/model/resource/ResourceModel"必需bundleName:"demo.i18n.i18n",supportedLocales:["],fallbackLocale:",异步:是,//<-});i18nModel.getResourceBundle().then(resourceBundle => {this.getOwnerComponent().setModel(i18nModel,"i18n");resourceBundle.getText(/*...*/);//参见sap/base/i18n/ResourceBundle});  

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

    仍然有一些API,它们还没有异步替代品,例如:

    • 正在获取 CLDR文件实例化 sap/ui/core/LocaleData 时使用同步XHR(例如在Calendar或DatePicker中使用.请参见问题#2345 ).
    • manifest.json
    • 中解析类似于i18n Handlebar的" {{...}}" -syntax时

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


    要回答这个问题: sap.ui.define sap.ui.require 确实会异步加载依赖项,如果 数据-sap-ui-async 配置设置为 true (替换 data-sap-ui-preload =异步" ).还要确保将依赖库添加到 manifest.json 中,以防止出现重大性能瓶颈.

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

     新的ComponentContainer({高度:"100%",名称:"webapp",异步:true,//或manifest:true,//自动将`async`选项设置为true }) 

    I'm staring my UI5 with the following bootstrapping in 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");
    });
    

    According to the 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.

    Do I understand it correctly that in such case the modules will be always loaded in a synchronous way and there is no real way to avoid the «Synchronous XMLHttpRequest on the main thread» warning?

    Can I, perhaps, just wrap new sap.m.Shell(sId?, mSettings?) with async/await?

    Update #1:

    I've checked the loading with ?sap-ui-xx-nosync=warn and got the following results:

    For some reason i18n/i18n_en.properties is loaded synchronously. The only place where I'm accessing the i18n is:

    const oBundle = myI18nModel.getResourceBundle();
    

    But following the documentation, I could not grasp why myI18nModel.getResourceBundle() leads to the synchronous loading.

    Update #2:

    After a deep exploration of no sync XHR sample, I found out the reason for the sync XHR warning. That was "description": "{{appDescription}}" and "title": "{{appTitle}}" in manifest.json which is explicitly noted:

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

    After replacing it with a static values the warning is gone.

    解决方案

    Early development of UI5 was heavily based on synchronous XHRs. Legacy applications or some outdated documentation topics might still refer to APIs that have either the asynchronous option disabled by default or no async option at all such as: sap.ui.controller, sap.ui.component, sap.ui.*fragment, sap.ui.*view, jQuery.sap.require, sap.ui.requireSync, jQuery.sap.sjax, and the constructor function of the ComponentContainer as mentioned in the question.

    In order to reduce the number of sync XHR calls:

    1. Follow the documented guidelines:

      Particularly when bootstrapping, use the data-sap-ui-async="true" option, and, if the app has a Component.js, use the declarative sap/ui/core/ComponentSupport module in data-sap-ui-oninit instead of instantiating sap.ui.core.ComponentContainer manually. For example:

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

      This automatically creates a ComponentContainer, pushes it to the DOM, and loads the Component.js and manifest.json asynchronously altogether while avoiding inline scripts or a separate bootstrap script at the same time.

    1. Run the app with the xx-nosync bootstrap option. For example, in the URL:

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

      UI5 will then log "loading … with sync XHR" in the browser console for each of the files fetched synchronously (Ignore other [nosync] messages). For example:

      • If the app uses a v2.ODataModel, it might complain that the module sap/ui/thirdparty/datajs was loaded synchronously. In that case, add the following to the bootstrap config:

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

      • If a ResourceModel is created manually in JS, make sure to enable the async flag there:

        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
        });

      Check the API reference of the reported APIs. Most of the times, they're either deprecated or they come with an async flag set to false by default.

    There are still some APIs left which have no asynchronous replacements yet such as:

    • The CLDR file being fetched with sync XHR when instantiating sap/ui/core/LocaleData (Used in e.g. Calendar or DatePicker. See Issue #2345).
    • When resolving i18n Handlebar-like "{{...}}"-syntax in manifest.json

    With the latest stable version of UI5, however, most of the synchronous requests can be eliminated.
    Here is a sample that has no sync XHR: https://embed.plnkr.co/7txzTsNwOBDbyi87


    To answer the question: sap.ui.define and sap.ui.require do load dependencies asynchronously if the data-sap-ui-async config is set to true (Replaces data-sap-ui-preload="async"). Also make sure to add dependent libs to the manifest.json in order to prevent a major performance bottleneck.

    Wrapping a synchronous content request with async-await/Promise won't unfortunately help. Better look for asynchronous alternatives. For example, the ComponentContainer has an async flag in the constructor settings which, if enabled, fetches the Component.js and manifest.json files asynchronously:

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

    这篇关于如何避免“主线程上的同步XMLHttpRequest"?UI5中警告?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆