DannyBoy
DannyBoy

Reputation: 444

How to run one getJSON after another based on the results of the first one

In my application, I am trying to gather data from two different sources. So first it has to loop.each in to an internal JSON file and see if the data is found, if not, it has to request another $.getjson() to get the data from an external source.

So the second $.getjson() is dependant on the first one and sometimes does not need to be run if the the data is already found in the first one.

First $.getjson() call:

$.getJSON(InternalURL, function (data) {
     $.each(data.Source, function (index, value) {
           if(artist.indexOf(value.keyword) > -1){
                 image = value.image;
                 $(".bg").css("background-image", "url(" + image + ")");
           }
     });

 });

Second $.getjson() call:

$.getJSON(ExternalURL, function (data) {
    image = data.artist.image;
    (".bg").css("background-image", "url(" + image + ")");
});

The other consideration is the timing of this process. Of course it has to be done as fast as possible, so the it wont be noticeable in the interface.

UPDATE Example using Async / Await based on the answer provided by @Tiny Giant JSFiddle Currently this code works on JSFiddle, but in the actual application, while it works fine, it gives a Console error as "Uncaught (in promise)" with an object of methods such as, always, abort, fail, and etc. Any idea why this error comes up?

Upvotes: 1

Views: 1482

Answers (2)

user4639281
user4639281

Reputation:

You could use Async / Await (initially defined in the ECMAScript® 2017 Language Specification). See caniuse.com for information on current support.

This works by pausing the current execution context and removing it from the stack once the getJSON call begins. Once the $.getJSON call returns, the paused execution context will be added back onto the stack, then execution will continue once the preceding items in the stack have been processed.

(async () => {
    const post = await $.getJSON('https://jsonplaceholder.typicode.com/posts/1');
    const comments = await $.getJSON('https://jsonplaceholder.typicode.com/comments');
    post.comments = comments.filter(e => e.postId === post.id);
    console.log(post);
})();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

To apply this to your specific example, you could use the following code:

(async () => {
    let image, data = await $.getJSON(InternalURL);
    if(data) {
        for(let value of data.Source) {
            if(!image && artist.indexOf(value.keyword) > -1) {
                image = value.image;
            }
        }
    } else {
        // request failed
    }
    if(!image) {
        let data = await $.getJSON(ExternalURL);
        if(data) {
            image = data.artist.image;
        } else {
            // request failed
        }
    }
    $(".bg").css("background-image", "url(" + image + ")");
})();

This requests the first resource, then—once that request is completed and execution is continued—it checks the response as your example does. If the script doesn't find what it is looking for in the first response, it initiates the second request. Once execution is continued, it sets the background image.

Further reading:


Another option would be to use callbacks. This method is more difficult to follow, but is supported everywhere.

$.getJSON('https://jsonplaceholder.typicode.com/posts/1', post => {
    $.getJSON('https://jsonplaceholder.typicode.com/comments', comments => {
        post.comments = comments.filter(e => e.postId === post.id);
        console.log(post);
    });
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

Upvotes: 3

Termhn
Termhn

Reputation: 129

$.getJSON(InternalURL, function (data) {
     $.each(data.Source, function (index, value) {
           if(artist.includes(value.keyword)){
                 if (value.image) {
                     image = value.image;
                     $(".bg").css("background-image", "url(" + image + ")");
                 } else {
                     $.getJSON(ExternalURL, function (data) {
                         image = data.artist.image;
                         (".bg").css("background-image", "url(" + image + ")");
                     });
                 }
           }
     });
 });

Upvotes: 1

Related Questions