How to Ensure Make Sure I'm Not Accessing Data Until It's Loaded In

How to prevent HTML from loading until all server data is processed?

Rather than window.onload, use $.when($.ajax()).then():

Option 1:

Create every element using document.createElement:

//window.onload = () => {
$.when($.ajax("file.txt")).then((data, textStatus, jqXHR) => {
var elements = [];
elements.push(document.createElement('div'));
});

And the only element that should be in the <body> would be your gif:

<body>
<img src="loading.gif" alt="Loading...">
</body>

Option 2:

Set every element to have display: none;:

<head>
<style>
* {
display: none;
}
</style>
</head>
<body>
<!-- other elements -->
<img src="loading.gif" alt="Loading..." onload="(event) => event.target.style.display = 'block'">
</body>

And again wait for the call to finish and set everything to block:

$.when($.ajax("file.txt")).then((data, textStatus, jqXHR) => {
$("*").css("display", "block");
});

CheerioCrawler: How do I ensure a page is fully loaded before extracting the data?

The potential problem is that the webpage loads some content using asynchronous XHR calls made with JavaScript. With the CheerioScraper you will get data from the first request on that site. If you want to load asynchronous content, you need to use the browser to open the page.

You can do it merely with using PuppeteerCrawler. It has quite a similar interface as CheerioCrawler. It opens webpage for each request. You can use there various waitFor functions from puppeteer page interface to wait for the content you want to get.

How to ensure that MonoBehaviour object has loaded its data before another Actor wants to access it?

My general shortrule is always

  • Use Awake for everything where you do not depend on others so setting up your own values, for setting up all references between components (but without using their values yet), stuff where you can use static classes.

    Also use this if possible for long taking loading/IO so it is done during the application loads and doesn't appear as lag for the user.

  • Use Start for everything where you need other components be already setup for e.g. using the values of references that have been setup in Awake.

also see Awake and Start Tutorial


This has its limits ofcourse so when needed you can start manipulating the Script Execution Order but I avoid that as much as possible.


If it gets really complex there sometimes isn't really a way around using an event system like e.g.

public class A : MonoBehaviour
{
public event Action OnReady;
public bool isReady;

private void Awake()
{
// do your stuff

isReady = true;

// execute whatever was added as callback
OnReady?.Invoke();
}
}

and than add callbacks where needed like e.g.

public class B : MonoBehaviour
{
// either reference it in the Inspector
public A a;

private void Awake()
{
// or get it somehow on runtime
a = FindObjectOfType<A>();

// if ready directly move on otherwise add callbacks
if(a.isReady)
{
OnAReady();
}
else
{
// it is always good to remove the callback even though
// it wasn't added yet. Makes sure it is always only added once
a.OnReady -= OnAReady;
a.OnReady += OnAReady;
}
}

private void OnDestroy()
{
// always remove callbacks when no longer needed
a.OnReady -= OnAReady;
}

private void OnAReady()
{
// always remove callbacks when no longer needed
a.OnReady -= OnAReady;

// use stuff from A
}
}

That looks more annyoing and complex but is way more efficient than waiting for some only-do-it-once event in the Update method.

React : How to make sure that requested data are available before rendering?

I usually use a spinner to indicate that the widget is loading:

render() {
return this.state.loading ? (
<div className="spinner">
<Spinner />
</div>
) : this.renderView();
}

renderView() does the actual rendering when state.loading is false. When state.loading is true, a spinner is displayed.

In componentWillMount, I set loading to true before making the API call.

componentWillMount() {
this.setState({loading: true});
ajaxCall().then(responses => {
// process response
this.setState({loading: false});
});
}

Load state/data before render?

So the error is telling you that in your redux state that state.user.user is undefined, this is why you can't destructure firstName, lastName, email values.

If in your store state.user.user is at least a defined, empty object ({}) then the access of null errors should resolve.

const userReducer = (state = { user: {} }, action) => {
...
}

This can still potentially leave your UI rendering "undefined", so in the component code you'll want to provide default values, i.e.

const { firstName = '', lastName = '', email = '' } = useSelector(
(state) => state.user.user
);

The alternative is to have fully qualified initial state in your user reducer slice.

const initialState = {
user: {
firstName: '',
lastName: '',
email: '',
},
};

const userReducer = (state = initialState, action) => {
...
}

Angular - Wait until I receive data before loading template

After studying the different approaches that people gave me, I found the solution on the async pipe. But, it took me a while to understand how to implement it.

Solution:

// Declaring the Promise, yes! Promise!
filtersLoaded: Promise<boolean>;

// Later in the Component, where I gather the data, I set the resolve() of the Promise
this.getFiltersSubscription = this.getFilters().subscribe(
(filters) => {
this.filters = filters;
log.info('API CALL. getting filters');

this.filtersLoaded = Promise.resolve(true); // Setting the Promise as resolved after I have the needed data
}
);

// In this listener triggered by the dynamic components when instanced,
// I pass the data, knowing that is defined because of the template change

// Listens to field's init and creates the fieldset triggering a service call
// that will be listened by the field component
this.iboService.initIBOsFilters$.subscribe(
(fieldName) => {
if (fieldName === 'IBOsRankSelectorFieldComponent') {
log.data('inside initIBOsFilters$ subscription, calling updateIBOsFilters()', fieldName);
this.iboService.updateIBOsRankList(this.filters['iboRank'].data);
}
}
);

In the template, I use the async pipe that needs an Observable or a Promise

<div *ngIf="filtersLoaded | async">
<div [saJquiAccordion]="{active: group.value['collapsed']}" *ngFor="let group of filterGroupsTemplate | keysCheckDisplay;">
<div>
<h4>{{group.key | i18n}}</h4>
<form id="ibo-{{group.key}}" class="form-horizontal" autocomplete="off" style="overflow: initial">
<fieldset *ngFor="let field of group.value | keys">
<ng-container *ngComponentOutlet="fieldSets[field.value.template];
ngModuleFactory: smartadminFormsModule;"></ng-container>
</fieldset>
</form>
</div>
</div>
</div>

NOTE:

  • async pipe need an Observable or a Promise from what I understood, that's why the only way to make it work was by creating a Promise
  • I didn't use the resolver approach because it's used when you arrive to the component through Angular's routing. This component is part of a larger component and it's not instanced through routing like any other normal component. (Tried that approach though, worked a bit with it, didn't do the job)


Related Topics



Leave a reply



Submit