JavaScript более быстрый способ запросить нулевое значение

#javascript

#javascript

Вопрос:

У меня вопрос. Я создал следующие функции:

 function checkGender(canidate, callback) {

    var query = "SELECT a.* FROM (SELECT Id AS GebruikerId, TIMESTAMPDIFF(year, profiel_Geboortedatum, NOW()) AS Leeftijd FROM "   
    "gebruikers WHERE Id = "   canidate.MedereizigerId   ") a INNER JOIN gebruikers ON gebruikers.Id = "   canidate.GebruikerId   " WHERE a.Leeftijd >= gebruikers.medereiziger_MinLeeftijd AND "   
    "a.Leeftijd <= gebruikers.medereiziger_MaxLeeftijd GROUP BY a.GebruikerId;";
    
    FYSCloud.API.queryDatabase(query).done(function (data) {
    
        if (data.length == 1) {
            callback(data);
        }
        else {
            callback(null);
        }
    
    }).fail(function (reason) {
        console.log(reason);
        callback(null);
    });
}



function checkAge(canidate, callback) {

    var query = "SELECT a.* FROM (SELECT Id AS GebruikerId, TIMESTAMPDIFF(year, profiel_Geboortedatum, NOW()) AS Leeftijd FROM "   
    "gebruikers WHERE Id = "   canidate.MedereizigerId   ") a INNER JOIN gebruikers ON gebruikers.Id = "   canidate.GebruikerId   " WHERE a.Leeftijd >= gebruikers.medereiziger_MinLeeftijd AND "   
    "a.Leeftijd <= gebruikers.medereiziger_MaxLeeftijd GROUP BY a.GebruikerId;";
    
    FYSCloud.API.queryDatabase(query).done(function (data) {
    
        if (data.length == 1) {
            callback(data);
        }
        else {
            callback(null);
        }
    
    }).fail(function (reason) {
        console.log(reason);
        callback(null);
    });
}

[...]
 

Теперь запросы работают как шарм, но я использую следующий код для вызова этих функций:

 for(var i=0; i<data.length; i  ) {
        
    // CHECK GESLACHT
    checkGender(data[i], function(genderData) {
        if(genderData != null) {
            
            // CHECK LEEFTIJD
            checkAge(data[i], function(ageData) {
                if(ageData != null) {
                
                    // CHECK BUDGET
                    checkBudget(data[i], function(budgetData) {
                        if(budgetData != null) {
            
                            // CHECK VAKANTIELAND
                            checkDestinationCountries(data[i], function(destinationCountryData) {
                                if(destinationCountryData != null) {
                
                                    // CHECK GESPROKEN TALEN
                                    checkSpokenLanguages(data[i], function(spokenLanguagesData) {
                                        if(spokenLanguagesData != null) {
                                            
                                        }
                                    });
                                }
                            });
                        }
                    });
                }
            });
        }
    });
}
 

То, что я здесь делаю, — это ожидание завершения функции, а затем переход к следующему, но только в том случае, если результат функции не вернулся null . Теперь это занимает много строк и вкладок, поэтому мне было интересно, есть ли лучший способ каждый раз запрашивать нулевое значение?

Пожалуйста, дайте мне знать, просто из любопытства

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

1. В вашем коде есть распространенная ошибка. Вы используете var i в своем цикле, а код внутри него используется i асинхронно. Внутри обратных вызовов для каждой отдельной итерации значение i будет равно data.length , потому что цикл завершится, и все обратные вызовы будут по-прежнему выполняться, но с конечным значением i . Вам нужно изолировать область действия i для каждой итерации, используя let i вместо var i

2. Спасибо @blex! Не могли бы вы взглянуть на комментарий к ответу ниже, потому что я что-то не понимаю в его ответе. Может быть, вы знаете ответ?

3. Использование Promises сделает ваш код намного более читабельным, с гораздо меньшим количеством отступов (то, что у вас здесь, называется «ад обратного вызова» ). Какую библиотеку вы используете для создания запросов к БД?

4. В моем колледже есть API, который мне нужно использовать, я не вижу кода, стоящего за ним…. Очень неубедительно: (

5. checkGender и checkAge сделайте то же самое, зачем нужно вызывать его дважды с разными именами? (это важно, потому что рекомендуемым способом здесь было бы переписать эти функции так, чтобы у вас был один queryDB(type, candidate) , который действительно мог бы возвращать обещание.)

Ответ №1:

Вы можете изменить свою функцию на результат, основанный на обещании, вместо вызова обратных вызовов используйте resolve и reject, например:

 function checkAge(canidate) {

    // create a new Promise and return it
    return new Promise((resolve, reject) => {
        var query = "SELECT a.* FROM (SELECT Id AS GebruikerId, TIMESTAMPDIFF(year, profiel_Geboortedatum, NOW()) AS Leeftijd FROM "   
        "gebruikers WHERE Id = "   canidate.MedereizigerId   ") a INNER JOIN gebruikers ON gebruikers.Id = "   canidate.GebruikerId   " WHERE a.Leeftijd >= gebruikers.medereiziger_MinLeeftijd AND "   
        "a.Leeftijd <= gebruikers.medereiziger_MaxLeeftijd GROUP BY a.GebruikerId;";
        
        FYSCloud.API.queryDatabase(query).done(function (data) {
            if (data.length == 1) {
                resolve(data); // when successful, resolve with data
            }
            else {
                reject('no data found'); // any error, call reject()
            }
        
        }).fail(function (reason) {
            console.log(reason);
            reject(reason); // any error, call reject()
        });
    });
}
 

С помощью этого вы можете использовать функцию async / await для написания общего метода проверки со всеми другими функциями проверки, поскольку любой вызов reject вызовет исключение:

 async function checkData(data) {
    try {
        const genderData = await checkGender(data);
        const ageData = await checkAge(data);
        const budgetData = await checkBudget(data);
        const destinationCountryData = await checkDestinationCountries(data);
    } catch (e) {
        // some validation failed
    }
}
 

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

1. Мне все еще нужно использовать данные, которые возвращают функции проверки !?

2. извините, я совершенно забыл об этом… Я редактирую вопрос, вы можете использовать результат promise, resolve метод вернет переданное ему значение

3. И я хочу, чтобы функция checkData возвращала строку, которая была создана при попытке после ожидания. Теперь, когда я делаю следующее в другой функции: var matchHTML = checkData(data[i]); и печатаю matchHTML, он говорит: [object Promise] . Что я делаю не так?

4. @A.Vreeswijk Вот несколько примеров использования приведенного выше кода: pastebin.com/embed_iframe/aDbwYD8U (предполагая, что вы return используете HTML в try , и return null; в catch )

5. Мне нужно добавить matchHTML к существующей строковой переменной с помощью concat, но когда я это делаю: checkData(data[i]).then(returnValue => matchHTML = matchHTML.concat(returnValue)); она не добавляется !?

Ответ №2:

Вы можете использовать amp;amp; оператор для проверки ложного значения (null, 0, false, undefined и т.д.) Перед выполнением функции.

value amp;amp; functionCall(value)

Это может сделать его немного чище.

 checkGender(data[i], genderData => genderData amp;amp;
    checkAge(data[i], ageData => ageData amp;amp;
        checkBudget(data[i], budgetData => budgetData amp;amp;
            checkDestinationCountries(data[i], destinationCountryData => destinationCountryData amp;amp;
                checkSpokenLanguages(data[i], spokenLanguagesData => spokenLanguagesData amp;amp; console.log("It Works"))))))
 

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

1. Почему genderData между () и ageData нет, budgetData опять же?

2. @A.Vreeswijk Для этого нет причин, если функция со стрелкой принимает только 1 параметр, круглые скобки являются необязательными

3. И как я могу начать кодирование внутри функций, потому что теперь у меня есть следующее в последней строке: checkSpokenLanguages(data[i], spokenLanguagesData => spokenLanguagesData amp;amp; console.log("IT WORKS!!!"); ))))); Но это выдает ошибку: Uncaught SyntaxError: missing ) after argument list

4. Добавил это в код. Не ставьте ; after console.log для функции со стрелкой. Если вам нужно тело, то вам нужно добавить { } после => .

5. Извините, вам не нужны параметры () вокруг. Это необязательно.