Можете ли вы помочь мне понять, как исправить этот асинхронный код?

#javascript #jquery #asynchronous #synchronous

#javascript #jquery #асинхронный #синхронный

Вопрос:

Я новичок в Javascript и испытываю серьезные проблемы, пытаясь понять асинхронный код и как им управлять. Моя главная проблема, из-за которой все это началось, заключается в том, что я пытаюсь прочитать объект JSON (в quotesList) с помощью http-запроса и сохранить его в глобальном для последующего использования. При попытке запустить мой код, поскольку он выполняется асинхронно, объект будет отображаться в других функциях как неопределенный, поскольку функция, определяющая его, к тому времени еще не завершилась. Я просто не знаю, как это решить.

Любая помощь приветствуется!

 let requestURL = 'https://gist.githubusercontent.com/nasrulhazim/54b659e43b1035215cd0ba1d4577ee80/raw/e3c6895ce42069f0ee7e991229064f167fe8ccdc/quotes.json'
var quotesList; 
var x = 5; 

var colors = [
    "EE6D51",
    "72EE51",
    "E7EA27",
    "FFA428",
    "28FF4F",
    "456CFC",
    "A645FC",
    "FC459B",
    "FC458A",
    "FE2842",
    "28FED4"
]


function getQuotes() {
    let request = new XMLHttpRequest(); 
    request.open('GET', requestURL);
    request.responseType = 'json'; 
    request.send(); 

    request.onload = function() {
        quotesList = request.response; 
        if (quotesList == null) {
            alert("Something's definitely wrong here...");
        }
        console.log('quotesList');
        console.log(quotesList);
    }
}

function populate() {
    var x = Math.floor(Math.random() * Math.floor(quotesList.quotes.length)); 
    document.getElementById('quote').innerHTML = quotesList.quotes[x].quote;
    document.getElementById('author').innerHTML = quotesList.quotes[x].author;
}

$(function() {

    getQuotes()
    populate

    while(($('.container strong ').height() >= 300)) {
        $('.container strong').css('font-size', (parseInt($('.container strong').css('font-size')) - 10.5)   "px");
        $('.container h3').css('font-size', (parseInt($('.container h3').css('font-size')) - 7.5)   "px");
    }
});
  

Комментарии:

1. » сохраните это в глобальном для последующего использования». — нет. Просто вызовите populate(quotesList) из onload обратного вызова напрямую и передайте значение в качестве аргумента. Не используйте глобальную переменную. (И, вероятно, вам придется переместить код форматирования высоты в populate )

2. Но разве мне не нужно было бы получать кавычки каждый раз, когда я хочу заполнить html-элемент? Я хочу, чтобы список цитат был доступен, когда пользователь выбирает «следующую цитату». Не было бы сложнее иметь локальный?

3. Извините, было неясно, что пользователь может выбрать «следующую цитату». В этом случае вы должны populate отобразить одну цитату и кнопку для отображения следующей, чтобы прослушиватель событий на следующей кнопке quotesList также имел доступ к . Для этого не обязательно быть глобальным.

Ответ №1:

Вам следует подробнее прочитать о promises, async / await

Вот ваш рабочий код (это работает только в новых браузерах (например, без IE), иначе вам понадобится babel для переноса кода async await)

 let requestURL = 'https://gist.githubusercontent.com/nasrulhazim/54b659e43b1035215cd0ba1d4577ee80/raw/e3c6895ce42069f0ee7e991229064f167fe8ccdc/quotes.json'
var quotesList; 
var x = 5; 

var colors = [
    "EE6D51",
    "72EE51",
    "E7EA27",
    "FFA428",
    "28FF4F",
    "456CFC",
    "A645FC",
    "FC459B",
    "FC458A",
    "FE2842",
    "28FED4"
]


function getQuotes() {
 return new Promise(function (resolve, reject) {
    let request = new XMLHttpRequest(); 
    request.open('GET', requestURL);
    request.responseType = 'json'; 
    
    request.onload = function() {
        let status = request.status;
        quotesList = request.response; 
        if (quotesList == null) {
            alert("Something's definitely wrong here...");
        }
        console.log('quotesList');
        console.log(quotesList);
        if (status == 200) {
            resolve(request.response);
        } else {
            reject(status);
        }
    }
    
    request.send(); 
    });
}

function populate() {
    var x = Math.floor(Math.random() * Math.floor(quotesList.quotes.length)); 
    document.getElementById('quote').innerHTML = quotesList.quotes[x].quote;
    document.getElementById('author').innerHTML = uotesList.quotes[x].author;
}

async function start(){
    await getQuotes();
    populate();
}

$(function() {

    start();

    while(($('.container strong ').height() >= 300)) {
        $('.container strong').css('font-size', (parseInt($('.container strong').css('font-size')) - 10.5)   "px");
        $('.container h3').css('font-size', (parseInt($('.container h3').css('font-size')) - 7.5)   "px");
    }
});