> For the complete documentation index, see [llms.txt](https://manual.bubble.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://manual.bubble.io/account-and-marketplace/building-plugins/loading-data.md).

# Loading data

<details>

<summary>System hard limits</summary>

When creating plugins for Bubble, it's important to be mindful of the Bubble's hard system limits. These constraints for plugin development mirror those present in general Bubble development. The article below covers this subject:

Article: [Hard limits](/help-guides/maintaining-an-application/performance-and-scaling/hard-limits.md)

</details>

When you access properties of type `Object` or `List of Objects`, you may request data that hasn't yet been sent from the Bubble server to the user's browser. For example, if you have a list property called `my_list` and you call `properties.my_list.get(0, 99)`, the first 100 entries often won't have been fetched from the server yet.

Experienced JavaScript programmers will be used to loading data asynchronously through callback functions. Bubble takes a different approach and handles data loading automatically behind the scenes. For the most part, you can write your code as if a call like `properties.my_list.get(0, 99)` returns immediately, even though Bubble may have to request the data from the server first.

## How data loading works

Most of the time this won't make a practical difference to you, but in certain situations it can lead to unexpected results if you don't understand what's happening underneath.

When your code requests data the browser doesn't have yet, Bubble does two things:

{% stepper %}
{% step %}

#### Request the data

Bubble immediately kicks off an asynchronous request to the server to load the data.
{% endstep %}

{% step %}

#### Pause your function

Bubble throws a special error that stops your function from running and tells the API it's waiting on the data.
{% endstep %}

{% step %}

#### Restart your function

Once the data has loaded, Bubble restarts your function. This time, when execution reaches the line requesting the data, it's available, and the function continues.
{% endstep %}
{% endstepper %}

## What this means for your code

This behind-the-scenes mechanism has two practical consequences:

<table><thead><tr><th width="263.96484375">Consequence</th><th>What to expect</th></tr></thead><tbody><tr><td>Functions can run more than once</td><td>A function you expect to run once, like an action, can run multiple times as Bubble incrementally loads the data it requests. Similarly, an element's <code>update</code> function re-runs not only when a property changes, but whenever requested data finishes loading or later changes.</td></tr><tr><td><code>try...catch</code> can interfere</td><td>A <code>try...catch</code> statement that wraps a data-loading call will catch the special error Bubble throws, which can stop this mechanism from working properly.</td></tr></tbody></table>

## Best practices

To keep these behaviors from causing bugs, follow three practices.

### Load data at the start of your functions

Always load data at the beginning of a function, before modifying any state outside it. For example, if you're writing an element that takes a list and renders it in the browser, load the list items you'll display, along with any fields on those items, before modifying the DOM.

The reason: if any of the data isn't ready yet, your code won't start making changes until all of it has loaded. If you instead load the first few list items, display them, then load more, you might accidentally display the first few items multiple times.

### Avoid asynchronous functions inside your functions

Don't run code inside a callback, such as:

```javascript
$(document).ready(function() {
    doSomething();
})
```

This breaks Bubble's dependency detection.

### Re-throw "not ready" errors from try...catch

Either avoid wrapping data-loading calls in a `try...catch`, or, if you need to, make sure you re-throw the special errors. You can detect them by checking the `message` property, which is set to `not ready`.

For example:

```javascript
try {
    var myData = properties.my_list.get(0, 99);
    doSomethingWith(myData);
} catch (err) {
    // Re-throw not-ready errors...
    if (err.message === 'not ready') {
        throw err;
    }
    // And handle other errors...
    myErrorHandlingLogic(err);
}
```
