Ваш код должен быть чем-то вроде этого:
function foo() {
var httpRequest = new XMLHttpRequest();
httpRequest.open('GET', "/echo/json");
httpRequest.send();
return httpRequest.responseText;
}
var result = foo(); // always ends up being 'undefined'
Феликс Клинг отлично справился с написанием ответа для людей, использующих jQuery для AJAX, я решил предоставить альтернативу для людей, которые этого не делают.
( Примечание. используя новый API fetch
, угловые или обещания, я добавил еще один ответ ниже )
Это краткое резюме «Объяснение проблемы» из другого ответа, если вы не уверены, прочитав это, прочитайте это.
A в AJAX означает асинхронность. Это означает, что отправка запроса (или, скорее, получение ответа) вынимается из обычного потока выполнения. В вашем примере .send
немедленно возвращается, а следующий оператор return result;
выполняется до того, как функция, которую вы передали, когда был вызван обратный вызов success
.
Это означает когда вы возвращаетесь, слушатель, который вы определили, еще не выполнил, что означает, что возвращаемое вами значение не было определено.
Вот простая аналогия
function getFive(){
var a;
setTimeout(function(){
a=5;
},10);
return a;
}
Возвращаемое значение a
- undefined
так как часть a=5
еще не выполнена. AJAX действует так, вы возвращаете значение до того, как сервер получил возможность сообщить вашему браузеру, что это за значение.
Одним из возможных решений этой проблемы является код повторно активно , сообщая вашей программе, что делать, когда расчет завершен.
function onComplete(a){ // When the code completes, do this
alert(a);
}
function getFive(whenDone){
var a;
setTimeout(function(){
a=5;
whenDone(a);
},10);
}
Это называется CPS . В основном, мы передаем getFive
действие, которое необходимо выполнить, когда оно завершается, мы сообщаем нашему кодексу, как реагировать, когда событие завершается (например, наш вызов AJAX или в этом случае время ожидания).
Использование будет:
getFive(onComplete);
Который должен предупредить «5» на экране. (Fiddle) .
Существуют два способа решения этой проблемы:
Что касается синхронного AJAX, не делайте этого! Ответ Феликса вызывает некоторые веские аргументы в пользу того, почему это плохая идея. Подводя итог, он заморозит браузер пользователя, пока сервер не вернет ответ и не создаст очень плохой пользовательский интерфейс. Вот еще краткое резюме из MDN о том, почему:
XMLHttpRequest поддерживает как синхронную, так и асинхронную связь. В общем, однако, асинхронные запросы должны быть предпочтительнее синхронных запросов по причинам производительности.
Короче говоря, синхронные запросы блокируют выполнение кода ... ... это может вызвать серьезные проблемы ...
Если вы имеете , вы можете передать флаг: Вот как это сделать:
var request = new XMLHttpRequest(); request.open('GET', 'yourURL', false); // `false` makes the request synchronous request.send(null); if (request.status === 200) {// That's HTTP for 'ok' console.log(request.responseText); }
2. Код реструктуризации
Пусть ваша функция принимает обратный вызов. В примере код
foo
может быть сделан для принятия обратного вызова. Мы сообщим нашему кодексу, как отреагировали , когдаfoo
завершает работу.Итак:
var result = foo(); // code that depends on `result` goes here
Становится:
foo(function(result) { // code that depends on `result` });
Здесь мы передали анонимную функцию, но мы могли бы так же легко передать ссылку на существующую , чтобы он выглядел следующим образом:
function myHandler(result) { // code that depends on `result` } foo(myHandler);
Для получения дополнительной информации о том, как выполняется этот вид обратного вызова, проверьте ответ Felix.
Теперь давайте определим сам foo, чтобы действовать соответственно
function foo(callback) { var httpRequest = new XMLHttpRequest(); httpRequest.onload = function(){ // when the request is loaded callback(httpRequest.responseText);// we're calling our method }; httpRequest.open('GET', "/echo/json"); httpRequest.send(); }
Теперь мы сделали нашу функцию foo принять действие, которое будет выполняться, когда AJAX завершится успешно, мы можем продолжить это, проверив, не является ли статус ответа не 200 и действует соответственно (создайте обработчик сбоя и т. д.). Эффективное решение нашей проблемы.
Если вам все еще трудно понять это , прочитайте руководство по началу работы AJAX в MDN.
Удаление sql-mode="STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION"
из my.ini решило проблему.
Изменить: Удаление строки выше работает, но это плохая идея. Он позволяет иметь такие вещи, как 0000-00-00 или пустые строки. Лучше держите линию выше и не вставляйте пустое жало в целочисленное поле, вместо этого конвертируйте пустую строку в NULL, а затем вставьте этот NULL в целочисленное поле.
Предполагая, что столбец допускает значения NULL
, вы должны явно указать MySQL, чтобы использовать значение NULL
, а не передавать пустую строку (которая передается в 0
):
INSERT INTO table (column_name) VALUES (NULL);
Есть два способа сделать это.
Сначала выполните запрос, чтобы получить текущий режим SQL вашего сервер mysql.
mysql> SELECT @@sql_mode;
+----------------------------------------------------------------+
| @@sql_mode |
+----------------------------------------------------------------+
|STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION |
+----------------------------------------------------------------+
1 row in set (0.00 sec)
Если результат содержит STRICT_TRANS_TABLES
, вы должны удалить это значение, чтобы разрешить вставить запрос для получения значения NULL. Убедитесь, что у пользователя mysql есть привилегии для применения этих изменений и перезапуска сервера Mysql после его применения.
SET GLOBAL sql_mode = '';
Вы должны обновить файл my.cnf. Местоположение этого файла: \ etc \ my.cnf или \ etc \ mysql \ mysql.cnf
В [mysqld] будут установлены некоторые параметры по умолчанию, например
[mysqld]
innodb_file_per_table=1
default-storage-engine=MyISAM
performance-schema=0
max_allowed_packet=268435456
open_files_limit=10000
Просто добавьте одну строку под этим
sql-mode=""
Обязательно перезапустите Mysql Server после изменения этого файла. Обычно пользователь root будет владельцем файла, поэтому вам нужно войти в систему с пользователем root на сервере.
Для получения дополнительной информации, чтобы понять, что делает этот режим SQL.
STRICT_TRANS_TABLES
Включить строгий режим SQL для транзакционных систем хранения данных и, если возможно, для не транзакционных систем хранения. Подробнее см. Строгий режим SQL.
См. http://dev.mysql.com/doc/refman/5.7/en/sql-mode.html#sqlmode_strict_trans_tables
NO_AUTO_CREATE_USER
Предотвратить автоматическое создание отчетов пользователя GRANT, если это было бы иначе, если не указана информация об аутентификации. Оператор должен указать непустой пароль, используя IDENTIFIED BY или плагин аутентификации, используя IDENTIFIED WITH.
См. http://dev.mysql.com/doc/refman/5.7/en/sql-mode.html#sqlmode_no_auto_create_user
NO_ENGINE_SUBSTITUTION
Управляйте автоматической заменой механизма хранения по умолчанию, когда оператор, такой как CREATE TABLE или ALTER TABLE, указывает механизм хранения, который отключен или не скомпилирован.
См. http://dev.mysql.com/doc/refman/5.7/en/sql-mode.html#sqlmode_no_engine_substitution