bigbucky
bigbucky

Reputation: 417

function keeps returning undefined array using Async Await

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;
            };
            };
        });
    });
};

Upvotes: 0

Views: 108

Answers (1)

trincot
trincot

Reputation: 351384

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;
    });

Upvotes: 3

Related Questions