-1

Been googling and looking for an answer to this / best practice.

Let's say you have most of your javascript inside $(document).ready() for whatever reason, and inside there you have a function that you want to "fire" based on some external javascript function..

What would be the best way to do that? Simply moving the function to the global space isn't entirely a feasible option due to all the variables and stuff inside $(document).ready()

So in this example, there's external javascript that does an ajax request, so when the request is completed, data get's loaded on the page, and then I want to somehow be able to fire that function inside $(document).ready() when that external javascript ajax completes, but I can't simply call that function due to it not being in the global space.

Alfred
  • 23
  • 3
  • 2
    Well, the current best practice is to include your JavaScript code as a [module](//developer.mozilla.org/en/docs/Web/JavaScript/Guide/Modules) using `` and stop using jQuery. Why does your function need to be in global scope? Please see [Why can I not define functions in jQuery's document.ready()?](/q/1055767/4642212), [jQuery - function inside $(document).ready function](/q/6780890/4642212), and [Why are inline event handler attributes a bad idea in modern semantic HTML?](/q/11737873/4642212). Are you using [`.on`](//api.jquery.com/on)? – Sebastian Simon Feb 15 '23 at 14:09
  • So make a custom event and have that other code trigger it. – epascarello Feb 15 '23 at 14:14
  • Please [edit] your post and provide an example of your code and what you’re trying to do, exactly. – Sebastian Simon Feb 15 '23 at 14:20
  • 1
    Move all your code out of doc.ready, *namespace* your code, and expose the functions you want to be accessible. There's various options in [this SO question](https://stackoverflow.com/questions/881515/how-do-i-declare-a-namespace-in-javascript). ofc that answer was before *modules* were common, so use modules these days. – freedomn-m Feb 15 '23 at 19:35

2 Answers2

0

you can use a setter to cast there:

let ready = false
const observe = {}
function run(name, ...args) {
  if (observe[name]) observe[name](...args)
  else {
    let fn
    Object.defineProperty(observe, name, {
      get() {
        return fn
      },
      set(fnL) {
        fn = fnL
        fnL(...args)
      }
    })
  }
}
function set(name, fn) {
  observe[name] = fn
}

$(document).ready(() => {
  ready = true

  const textEl = $("#text")

  function setText(text) {
    textEl.text(text)
  }

  set('setText', setText)
})

run('setText', 'first run')

setTimeout(() => run('setText', 'delayed 2s'), 2000)
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<div id="text">no thing</div>

this is quite powerful if you call the function before $().ready has completed it will wait until $().ready runs. and if $().ready is already running it will call the function too

Usage

in $().ready you have to call set('<function name>', <function>) and when you want to call the function run run('<function name>', ...<argumentts> )

or simpler way you remove $().ready and type <script> at the end of <body> it will work

Tachibana Shin
  • 2,605
  • 1
  • 5
  • 9
0

If you do not want to expose a global then you can make an event that the code has to trigger which will inform when it is done.

$(function () {
  function myLocalFunction (e, data) {
    console.log('called', data);
  }

  $(document).on("loadedTheStuff", myLocalFunction);

});


window.setTimeout(function () {
   $(document).trigger("loadedTheStuff", "Hello!");
}, 300);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
epascarello
  • 204,599
  • 20
  • 195
  • 236