简体   繁体   中英

Issues in storing a portion of an AJAX GET response (in JSON) into a string variable

I have a problem trying to store part of the result of a GET request via AJAX into a string variable.

Basically, I wanted to make it so a certain function that contains a GET request operation would return the result of that operation.

var count = 0;

$.getJSON("https://api.icndb.com/jokes/count", function(data){ 
    count = data.value+1;
    for (i = 1; i < count; i++){ 
        if (i != 1) {
            setTimeout(jokeGet, i*7500, i);
        }
        else {
            jokeGet(i);
        }
    }
});

function jokeGet(n) {
    var str = "";
    $.getJSON("https://api.icndb.com/jokes/" + n, function(data){
        if (data.type != "NoSuchQuoteException") {
            $(".joke").html(data.value.joke);
            str = data.value.joke;
        }
        else {
            count++;
        }
    });

    return str;
}

The API I'm making the request(s) to stores the information in JSON trees. Here are two examples of such trees:

{ "type": "success", "value": { "id": 1, "joke": "Chuck Norris uses ribbed condoms inside out, so he gets the pleasure.", "categories": ["explicit"] } }

{ "type": "NoSuchQuoteException", "value": "No quote with id=8." }

However, whenever I run the unit tests (via QUnit), it turns out that, in any and all cases, the jokeGet() function returns an empty string. Which is something that I find strange, since I would think that the str = data.value.joke line would have made it so the joke was stored in that variable str .

Apparently, because str always returns as an empty string, that is not the case. Any suggestions as to why this is?

Update

Considering that the goal of what I am doing right now isn't to get the program to work but to make unit tests to demonstrate that the program works, I have decided to include the "unit tests" file:

QUnit.test("cn_jokes", function(assert) {
    function joke(n, expected) {
        assert.equal(jokeGet(n), expected);
    }
    joke(1, "Chuck Norris uses ribbed condoms inside out, so he gets the pleasure.");
    joke(8, undefined);
    joke(163, "Ninjas want to grow up to be just like Chuck Norris. But usually they grow up just to be killed by Chuck Norris.");
    joke(221, "Chuck Norris is the only person to ever win a staring contest against Ray Charles and Stevie Wonder.");
    joke(352, "Chuck Norris doesn't see dead people. He makes people dead.");
    joke(502, "Chuck Norris insists on strongly-typed programming languages.");
    joke(526, "No one has ever pair-programmed with Chuck Norris and lived to tell about it.");
    joke(598, "Once Chuck Norris and Superman had a competition. The loser had to wear his underwear over his pants.");
});

As you can see, I would like to get the jokeGet() function, specifically, to return the joke value. Please let me know whether this is possible.

$.getJSON is asynchronous; your code will continue to run while the request is made. Because of this, str is returned long before by the callback you pass to getJSON runs. You should probably have jokeGet take a callback function, and call it when the request is complete (passing data.value.joke as an argument):

function jokeGet(n, callback) {
    $.getJSON("https://api.icndb.com/jokes/" + n, function(data){
        if (data.type != "NoSuchQuoteException") {
            $(".joke").html(data.value.joke);
            if (callback !== undefined && callback !== null)
                callback(data.value.joke);
        }
        else {
            count++;
            if (callback !== undefined && callback !== null)
                callback(undefined); // not sure if you want undefined or "" in this case
        }
    });
}

EDIT: You can use asynchronous callbacks with QUnit. Just use assert.async() , as mentioned here :

QUnit.test("cn_jokes", function(assert) {
    var done = assert.async();
    var jokesDone = 0;
    var numJokes = 8; // make sure to change this if you add more
    function joke(n, expected) {
        jokeGet(n, function(j) {
            assert.equal(j, expected);
            if (++jokesDone == numJokes) done();
        }
    }
    joke(1, "Chuck Norris uses ribbed condoms inside out, so he gets the pleasure.");
    joke(8, undefined);
    joke(163, "Ninjas want to grow up to be just like Chuck Norris. But usually they grow up just to be killed by Chuck Norris.");
    joke(221, "Chuck Norris is the only person to ever win a staring contest against Ray Charles and Stevie Wonder.");
    joke(352, "Chuck Norris doesn't see dead people. He makes people dead.");
    joke(502, "Chuck Norris insists on strongly-typed programming languages.");
    joke(526, "No one has ever pair-programmed with Chuck Norris and lived to tell about it.");
    joke(598, "Once Chuck Norris and Superman had a competition. The loser had to wear his underwear over his pants.");
});

try using the return statement inside the if block

if(condition){
return str;
} else {
return
}

I guess this behavious is due to the async nature of js , it returns value before the get request is complete

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM