0

Can't get my getJSON function to return the array. I've been trying to use await/async but I'm doing something wrong.

.map and .filter should be synchronous but I've tried putting await on them as well.

$(function() {
    $("#roll").click(async function() {
    var x = await getTreasure()
    chrome.extension.getBackgroundPage().console.log(x)
    });
});

function getTreasure() {
    var sizeValue = $('input[name=size]:checked').val();
    var crValue = $('input[name=challenge]:checked').val();
    var die = Math.floor((Math.random() * 100) + 1);
    var url = "";

    if (sizeValue == "individual") {
        url = chrome.runtime.getURL("treasure_individual.json");
    } else {
        url = chrome.runtime.getURL("treasure_horde.json");
    };
    $.getJSON(url, function(data) {
        var match = data.treasure.filter(function (e) {
            return e.cr == crValue;
        });
        for (i in match[0].roll) {
            var str = match[0].roll[i].d100;
            var arr = str.match(/([0-9]+)/g);
            var levels = $.map(arr, function (x) { 
                return parseInt(x, 10); 
            });

            if (die == levels[0] || die >= levels[0] && die <= levels[1]) {
                chrome.extension.getBackgroundPage().console.log(levels);
                return levels;
            } else {
                return die;
            };
        };
    });
};

Edit: Ok, didn't understand await still needed a Promise. But I'm still not getting it. Tried adding the return Promise around the getJson function but it's still not returning levels.

function getTreasure() {
    var sizeValue = $('input[name=size]:checked').val();
    var crValue = $('input[name=challenge]:checked').val();
    var die = Math.floor((Math.random() * 100) + 1);
    var url = "";

    if (sizeValue == "individual") {
        url = chrome.runtime.getURL("treasure_individual.json");
    } else {
        url = chrome.runtime.getURL("treasure_horde.json");
    };

    return new Promise(resolve => {
    $.getJSON(url, function(data) {
        var match = data.treasure.filter(function (e) {
            return e.cr == crValue;
        });
        for (i in match[0].roll) {
            var str = match[0].roll[i].d100;
            var arr = str.match(/([0-9]+)/g);
            var levels = $.map(arr, function (x) { 
                return parseInt(x, 10); 
            });

            if (die == levels[0] || die >= levels[0] && die <= levels[1]) {
                //chrome.extension.getBackgroundPage().console.log(levels);
                return levels;
            };
            };
        });
    });
};
9
  • 1
    await only waits on a Promise. Your getTreasure() doesn't return one. Commented Nov 24, 2018 at 20:44
  • 1
    You will want to use return $.getJSON(url).then(function(data) { …. Maybe replace that then call with an await as well. Commented Nov 24, 2018 at 20:46
  • You never call resolve. But instead of new Promise, just return $.getJSON(...........).promise(). Commented Nov 24, 2018 at 22:30
  • 1
    @Xorifelse No need to use new Promise Commented Nov 24, 2018 at 22:49
  • 1
    @bigbucky, did you read the comments? Don't use new Promise here. It is bad practice! Also, don't put an answer inside your question. It makes any answers look stupid. Instead comment, vote and eventually: accept. Commented Nov 24, 2018 at 23:13

1 Answer 1

3

The way to return the promise is not by adding new Promise (which is an anti-pattern in this case), but to get the promise that jQuery already has for you:

    return $.getJSON(url, function(data) {
//  ^^^^^^
       // .......
    }).promise();
//    ^^^^^^^^^^

NB: in your second attempt you never called resolve.

If you need some specific data to be "promised", then chain a then instead of using the callback of $.getJSON. Like this:

    return $.getJSON(url).then(function(data) {
//  ^^^^^^               ^^^^^^
       // .......
       return levels;
    });
Sign up to request clarification or add additional context in comments.

6 Comments

I tried this but I was getting an error saying resolve was not defined. I probably was putting it in the wrong scope.
You should not have any resolve. That only makes sense when you have new Promise, which you should not need (it is bad practice)
Is this just because I'm using getJSON because I haven't seen promise() in the other stuff I've read. developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
promise() is a jQuery method on deferred objects ($.getJSON returns a deferred). See jQuery documentation of .promise().
If you need to have a promise for specific data, then use then. I've now added this possibility to my answer.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.