Uncaught ReferenceError: Api is not defined

Hi, Gusy.
It works fine on my localhost, but when I register the plugin on my test server, I get the following console error.
image

I have already checked this link.
https://developer.atlassian.com/server/jira/platform/web-resource/

atlassian-plugin.xml

<web-resource key="temp-test" name="temp-test">
        <dependency>com.atlassian.plugins.atlassian-plugins-webresource-plugin:i18n</dependency>
        <dependency>com.atlassian.auiplugin:ajs</dependency>
        <dependency>com.atlassian.auiplugin:aui-flag</dependency>
        <dependency>com.atlassian.auiplugin:aui-select</dependency>
        <dependency>com.atlassian.auiplugin:aui-select2</dependency>
        <dependency>com.atlassian.auiplugin:aui-table-sortable</dependency>
        <dependency>com.atlassian.auiplugin:aui-navigation</dependency>

        <transformation extension="js">
            <transformer key="jsI18n"/>
        </transformation>

        <resource type="download" name="temp-test.css" location="/css/temp-test.css"/>
        <resource type="download" name="temp-test.js" location="/js/temp-test.js"/>
        <resource type="download" name="images/" location="/images"/>

        <resource type="download" name="api.js" location="/js/api.js"/>
        <resource type="download" name="api-path.js" location="/js/api-path.js"/>
        <resource type="download" name="common.js" location="/js/utils/common.js"/>

        <context>atl.admin</context>
        <context>temp</context>

test.vm

<html>
    <head>
        <title>$i18n.getText("testtemp.menu.admin.section")</title>
        <meta charset="UTF-8">
        <meta name="decorator" content="temp">
        <meta name="decorator" content="atl.admin">
        <meta http-equiv="Expires" content="-1">
        <meta http-equiv="Pragma" content="no-cache">
        <meta http-equiv="Cache-Control" content="no-cache">
        <meta http-equiv="X-UA-Compatible" content="IE=EDGE">
##        $webResourceManager.requireResourcesForContext("temp")
        <script type="text/javascript">
          Api.call(~~~)

help…
Why does it work locally but not when I register the plugin?

Your JS file is probably not loaded yet when that inline script tries to run.

<script type='text/javascript'>
AJS.toInit(function () {
  Api.call(...);
});
</script>

Should do the trick

1 Like

Thanks PaoloCampanelli :slight_smile:
I’m really curious. It works fine locally. But when I register the plugin, it doesn’t work.

my api.js

console.log('api.js')

let Api = {
    call: function (url, type, data) {
        return new Promise(function (resolve, reject) {
            AJS.$.ajax({
                url: url,
                type: type,
                headers: {
                    Accept: 'application/json',
                    'Content-Type': 'application/json'
                },
                data: JSON.stringify(data),
                dataType: "json",
                timeout: 15000,
                cache: false,
                success: function (data) {
                    resolve(data);
                },
                error: function (xhr, textStatus, errorThrown) {
                    reject({ xhr, textStatus, errorThrown });
                }
            });
        });
    },
};

The plugin does a good job of logging console.log.

Think about what happens for your browser.

  1. The browser gets an HTML page from Jira and starts reading it top to bottom
  2. In the <head> you’ll have a <script> tag that wants to download api.js, the browser starts fetching it
  3. The browser reads the <body> of your page and renders it
  4. You have an inline <script> that tries invoking Api.call, the browser runs that code

Locally, fetching your api.js file is basically instantaneous since you have no network latency, so by the time your browser reaches step 4, Api is available.
On your test server, by the time you’re at step 4, the browser might still be fetching your js file, so your inline script won’t work.

Using AJS.toInit (or similar alternatives such as window.addEventListener('load', function() {})) tells your browser not to run the code in step 4 until all the external resources have been fetched.

Your console.log will always work since it runs as soon as api.js is loaded, which might be before or after step 4, but it doesn’t matter.

1 Like

Thank you so much for the feedback!!!
I found a solution to this problem and I think I can fix the code.

1 Like