#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. Добавил это в код. Не ставьте
;
afterconsole.log
для функции со стрелкой. Если вам нужно тело, то вам нужно добавить{ }
после=>
.5. Извините, вам не нужны параметры
()
вокруг. Это необязательно.