Как я могу вернуть ответ от асинхронного вызова?

У меня есть функция foo который делает запрос Ajax. Как я могу вернуть ответ от foo?

Я пытался вернуть значение из success обратный вызов, а также присваивание ответа локальной переменной внутри функции и его возврат, но ни один из этих способов фактически не возвращает ответ.

function foo() {
var result;

$.ajax({
url: '...',
success: function(response) {
result = response;
// return response; // <- I tried that one as well
}
});

return result;
}

var result = foo(); // It always ends up being `undefined`.

4706

Решение

→ Для более общего объяснения асинхронного поведения с различными примерами, пожалуйста, смотрите Почему моя переменная не изменилась после того, как я изменил ее внутри функции? — асинхронная ссылка на код

→ Если вы уже поняли проблему, перейдите к возможным решениям ниже.

в Ajax обозначает асинхронный . Это означает, что отправка запроса (или, вернее, получение ответа) исключается из обычного потока выполнения. В вашем примере $.ajax немедленно возвращается и следующее утверждение, return result;, выполняется перед функцией, которую вы передали как success Обратный звонок даже был вызван.

Вот аналогия, которая, надо надеяться, проясняет разницу между синхронным и асинхронным потоком:

синхронный

Представьте, что вы звоните другу и просите его найти что-то для вас. Хотя это может занять некоторое время, вы ждете по телефону и смотрите в пространство, пока ваш друг не даст вам ответ, который вам нужен.

То же самое происходит, когда вы делаете вызов функции, содержащий «нормальный» код:

function findItem() {
var item;
while(item_not_found) {
// search
}
return item;
}

var item = findItem();

// Do something with item
doSomethingElse();

Даже если findItem выполнение может занять много времени, любой код после var item = findItem(); должен Подождите пока функция не вернет результат.

Асинхронный

Вы звоните своему другу снова по той же причине. Но на этот раз вы говорите ему, что вы спешите, и он должен Вам позвоним на вашем мобильном телефоне. Вы вешаете трубку, выходите из дома и делаете все, что планировали. Как только ваш друг перезвонит вам, вы будете иметь дело с информацией, которую он вам дал.

Это именно то, что происходит, когда вы делаете запрос Ajax.

findItem(function(item) {
// Do something with item
});
doSomethingElse();

Вместо ожидания ответа выполнение продолжается немедленно и выполняется оператор после вызова Ajax. Чтобы в конечном итоге получить ответ, вы предоставляете функцию, которая будет вызываться после получения ответа, Перезвоните (заметить что-то? Перезвоните ?). Любой оператор, следующий за этим вызовом, выполняется до вызова обратного вызова.


Примите асинхронную природу JavaScript! Хотя некоторые асинхронные операции предоставляют синхронные аналоги (как и «Ajax»), их обычно не рекомендуется использовать, особенно в контексте браузера.

Почему это плохо, спросите вы?

JavaScript запускается в потоке пользовательского интерфейса браузера, и любой длительный процесс блокирует пользовательский интерфейс, что делает его неотзывчивым. Кроме того, существует верхний предел времени выполнения для JavaScript, и браузер спросит пользователя, продолжать ли выполнение или нет.

Все это действительно плохой пользовательский опыт. Пользователь не сможет сказать, все ли работает нормально или нет. Кроме того, эффект будет хуже для пользователей с медленным подключением.

Далее мы рассмотрим три различных решения, которые все строятся друг на друге:

  • Обещания с async/await (ES2017 +, доступно в старых браузерах, если вы используете транспортер или регенератор)
  • Callbacks (популярный в узле)
  • Обещания с then() (ES2015 +, доступно в старых браузерах, если вы используете одну из множества библиотек обещаний)

Все три доступны в текущих браузерах и узле 7+.


ES2017 +: обещания с async/await

Представлена ​​версия ECMAScript, выпущенная в 2017 году поддержка уровня синтаксиса для асинхронных функций. С помощью async а также awaitВы можете написать асинхронный в «синхронном стиле». Код все еще асинхронный, но его легче читать / понимать.

async/await основывается на обещаниях: async Функция всегда возвращает обещание. await «разворачивает» обещание и либо приводит к значению, с которым обещание было разрешено, либо выдает ошибку, если обещание было отклонено.

Важный: Вы можете использовать только await внутри async функция. Прямо сейчас, на высшем уровне await пока не поддерживается, поэтому вам может потребоваться сделать асинхронный IIFE, чтобы запустить async контекст.

Вы можете прочитать больше о async а также await на MDN.

Вот пример, который основан на задержке выше:

// Using 'superagent' which will return a promise.
var superagent = require('superagent')

// This is isn't declared as `async` because it already returns a promise
function delay() {
// `delay` returns a promise
return new Promise(function(resolve, reject) {
// Only `delay` is able to resolve or reject the promise
setTimeout(function() {
resolve(42); // After 3 seconds, resolve the promise with value 42
}, 3000);
});
}


async function getAllBooks() {
try {
// GET a list of book IDs of the current user
var bookIDs = await superagent.get('/user/books');
// wait for 3 seconds (just for the sake of this example)
await delay();
// GET information about each book
return await superagent.get('/books/ids='+JSON.stringify(bookIDs));
} catch(error) {
// If any of the awaited promises was rejected, this catch block
// would catch the rejection reason
return null;
}
}

// Start an IIFE to use `await` at the top level
(async function(){
let books = await getAllBooks();
console.log(books);
})();

Текущий браузер а также узел поддержка версий async/await, Вы также можете поддерживать более старые среды, преобразовав свой код в ES5 с помощью регенератор (или инструменты, которые используют регенератор, такие как галдеж).


Пусть функции принимают обратные вызовы

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

В примере вопроса вы можете сделать foo принять звонок и использовать его как success Перезвоните. Так это

var result = foo();
// Code that depends on 'result'

становится

foo(function(result) {
// Code that depends on 'result'
});

Здесь мы определили функцию «inline», но вы можете передать любую ссылку на функцию:

function myCallback(result) {
// Code that depends on 'result'
}

foo(myCallback);

foo само определяется следующим образом:

function foo(callback) {
$.ajax({
// ...
success: callback
});
}

callback будет ссылаться на функцию, которую мы передаем foo когда мы называем это, и мы просто передаем это success, То есть как только запрос Ajax будет успешным, $.ajax позвоню callback и передать ответ на обратный вызов (который может быть передан с помощью result, так как мы определили обратный вызов).

Вы также можете обработать ответ, прежде чем передать его обратному вызову:

function foo(callback) {
$.ajax({
// ...
success: function(response) {
// For example, filter the response
callback(filtered_response);
}
});
}

Написание кода с использованием обратных вызовов проще, чем может показаться. В конце концов, JavaScript в браузере сильно зависит от событий (события DOM). Получение ответа Ajax — не что иное, как событие.
Сложности могут возникнуть, когда вам приходится работать со сторонним кодом, но большинство проблем можно решить, просто продумав поток приложения.


ES2015 +: обещания с затем()

Promise API это новая функция ECMAScript 6 (ES2015), но она имеет хорошие поддержка браузера уже. Существует также много библиотек, которые реализуют стандартный API Promises и предоставляют дополнительные методы для упрощения использования и составления асинхронных функций (например, певчая птица).

Обещания являются контейнерами для будущее ценности. Когда обещание получает значение (это решены) или когда это отменено (отвергнуто), он уведомляет всех своих «слушателей», которые хотят получить доступ к этому значению.

Преимущество по сравнению с простыми обратными вызовами состоит в том, что они позволяют вам отделить ваш код, и их легче составлять.

Вот простой пример использования обещания:

function delay() {
// `delay` returns a promise
return new Promise(function(resolve, reject) {
// Only `delay` is able to resolve or reject the promise
setTimeout(function() {
resolve(42); // After 3 seconds, resolve the promise with value 42
}, 3000);
});
}

delay()
.then(function(v) { // `delay` returns a promise
console.log(v); // Log the value once it is resolved
})
.catch(function(v) {
// Or do something else if it is rejected
// (it would not happen in this example, since `reject` is not called).
});

Применительно к нашему вызову Ajax мы могли бы использовать такие обещания:

function ajax(url) {
return new Promise(function(resolve, reject) {
var xhr = new XMLHttpRequest();
xhr.onload = function() {
resolve(this.responseText);
};
xhr.onerror = reject;
xhr.open('GET', url);
xhr.send();
});
}

ajax("/echo/json")
.then(function(result) {
// Code depending on result
})
.catch(function() {
// An error occurred
});

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

Больше информации об обещаниях: HTML5 качается — JavaScript обещает

Примечание: отложенные объекты jQuery

Отложенные объекты пользовательская реализация обещаний в jQuery (до стандартизации API Promise). Они ведут себя почти как обещания, но выставляют немного другой API.

Каждый Ajax-метод jQuery уже возвращает «отложенный объект» (фактически обещание отложенного объекта), который вы можете просто вернуть из своей функции:

function ajax() {
return $.ajax(...);
}

ajax().done(function(result) {
// Code depending on result
}).fail(function() {
// An error occurred
});

Примечание: обещание получилось

Имейте в виду, что обещания и отложенные объекты просто контейнеры для будущей ценности они не являются самой ценностью. Например, предположим, у вас было следующее:

function checkPassword() {
return $.ajax({
url: '/password',
data: {
username: $('#username').val(),
password: $('#password').val()
},
type: 'POST',
dataType: 'json'
});
}

if (checkPassword()) {
// Tell the user they're logged in
}

Этот код неправильно понимает вышеуказанные проблемы асинхронности. В частности, $.ajax() не замораживает код, пока проверяет страницу «/ пароль» на вашем сервере — он отправляет запрос на сервер и, пока ожидает, немедленно возвращает объект JQuery Ajax Deferred, а не ответ от сервера. Это означает, что if оператор всегда будет получать этот отложенный объект, рассматривать его как trueи продолжайте, как если бы пользователь вошел в систему. Не хорошо.

Но исправить это легко:

checkPassword()
.done(function(r) {
if (r) {
// Tell the user they're logged in
} else {
// Tell the user their password was bad
}
})
.fail(function(x) {
// Tell the user something bad happened
});

Не рекомендуется: синхронные вызовы «Ajax»

Как я уже говорил, некоторые (!) Асинхронные операции имеют синхронные аналоги. Я не защищаю их использование, но для полноты картины, вот как вы должны выполнить синхронный вызов:

Без jQuery

Если вы напрямую используете XMLHTTPRequest объект, проход false в качестве третьего аргумента .open.

JQuery

Если вы используете JQuery, Вы можете установить async возможность false, Обратите внимание, что эта опция осуждается с jQuery 1.8.
Вы можете либо использовать success Обратный звонок или доступ к responseText собственность объект jqXHR:

function foo() {
var jqXHR = $.ajax({
//...
async: false
});
return jqXHR.responseText;
}

Если вы используете любой другой метод jQuery Ajax, такой как $.get, $.getJSONи т. д., вы должны изменить его на $.ajax (поскольку вы можете передавать только параметры конфигурации $.ajax).

Берегись! Невозможно сделать синхронный JSONP запрос. JSONP по своей природе всегда асинхронен (еще одна причина, чтобы даже не рассматривать эту опцию).

5029

Другие решения

Ваш код должен быть примерно таким:

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. Я решил предоставить альтернативу тем, кто этого не делает.

(Обратите внимание, для тех, кто использует новый fetch API, Angular или обещания Я добавил еще один ответ ниже)


Это краткое изложение «Объяснение проблемы» из другого ответа, если вы не уверены, прочитав это, прочитайте это.

в AJAX расшифровывается как асинхронный. Это означает, что отправка запроса (или, вернее, получение ответа) исключается из обычного потока выполнения. В вашем примере .send немедленно возвращается и следующее утверждение, return result;, выполняется перед функцией, которую вы передали как success Обратный звонок даже был вызван.

Это означает, что когда вы возвращаете, определенный слушатель еще не выполнялся, то есть возвращаемое вами значение не было определено.

Вот простая аналогия

function getFive(){
var a;
setTimeout(function(){
a=5;
},10);
return a;
}

(Fiddle)

Значение 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);
}

Это называется КПС. В основном мы проходим getFive действие, которое нужно выполнить после его завершения, мы сообщаем нашему коду, как реагировать на завершение события (например, наш вызов AJAX или в этом случае тайм-аут).

Использование будет:

getFive(onComplete);

Который должен предупредить «5» на экране. (Fiddle).

Есть два основных способа решения этой проблемы:

  1. Сделайте вызов AJAX синхронным (давайте назовем его SJAX).
  2. Реструктурируйте ваш код для правильной работы с обратными вызовами.

1. Синхронный AJAX — не делай этого !!

Что касается синхронного 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);

Для получения более подробной информации о том, как делается этот дизайн обратного вызова, проверьте ответ Феликса.

Теперь давайте определим сам 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.

+959

XMLHttpRequest 2 (прежде всего прочитайте ответы от Бенджамин Грюнбаум & Феликс Клинг)

Если вы не используете jQuery и хотите получить хороший короткий XMLHttpRequest 2, который работает в современных браузерах, а также в мобильных браузерах, я предлагаю использовать его следующим образом:

function ajax(a, b, c){ // URL, callback, just a placeholder
c = new XMLHttpRequest;
c.open('GET', a);
c.onload = b;
c.send()
}

Как вы видете:

  1. Это короче, чем все остальные функции, перечисленные.
  2. Обратный вызов устанавливается напрямую (поэтому никаких лишних ненужных замыканий).
  3. Он использует новую нагрузку (так что вам не нужно проверять состояние готовности) && статус)
  4. Есть некоторые другие ситуации, которые я не помню, которые делают XMLHttpRequest 1 раздражающим.

Есть два способа получить ответ на этот вызов Ajax (три с использованием имени переменной XMLHttpRequest):

Простейший:

this.response

Или если по какой-то причине вы bind() обратный вызов в класс:

e.target.response

Пример:

function callback(e){
console.log(this.response);
}
ajax('URL', callback);

Или (вышеприведенный лучше анонимные функции всегда проблема):

ajax('URL', function(e){console.log(this.response)});

Нет ничего проще.

Теперь некоторые люди, вероятно, скажут, что лучше использовать onreadystatechange или даже имя переменной XMLHttpRequest. Это неверно.

Проверять, выписываться XMLHttpRequest расширенные функции

Поддерживаются все * современные браузеры. И я могу подтвердить, что использую этот подход, так как существует XMLHttpRequest 2. У меня никогда не было никаких проблем во всех браузерах, которые я использую.

onreadystatechange полезен, только если вы хотите получить заголовки в состоянии 2.

С использованием XMLHttpRequest Имя переменной — еще одна большая ошибка, так как вам нужно выполнить обратный вызов внутри замыканий onload / oreadystatechange, иначе вы его потеряли.


Теперь, если вы хотите что-то более сложное, используя post и FormData, вы можете легко расширить эту функцию:

function x(a, b, e, d, c){ // URL, callback, method, formdata or {key:val},placeholder
c = new XMLHttpRequest;
c.open(e||'get', a);
c.onload = b;
c.send(d||null)
}

Опять же … это очень короткая функция, но она получает & сообщение.

Примеры использования:

x(url, callback); // By default it's get so no need to set
x(url, callback, 'post', {'key': 'val'}); // No need to set post data

Или передать полный элемент формы (document.getElementsByTagName('form')[0]):

var fd = new FormData(form);
x(url, callback, 'post', fd);

Или установите некоторые пользовательские значения:

var fd = new FormData();
fd.append('key', 'val')
x(url, callback, 'post', fd);

Как видите, я не реализовал синхронизацию … это плохо.

Сказав это … почему бы не сделать это простым способом?


Как уже упоминалось в комментарии, использование ошибки && синхронный полностью нарушает точку ответа. Какой хороший короткий способ правильно использовать Ajax?

Обработчик ошибок

function x(a, b, e, d, c){ // URL, callback, method, formdata or {key:val}, placeholder
c = new XMLHttpRequest;
c.open(e||'get', a);
c.onload = b;
c.onerror = error;
c.send(d||null)
}

function error(e){
console.log('--Error--', this.type);
console.log('this: ', this);
console.log('Event: ', e)
}
function displayAjax(e){
console.log(e, this);
}
x('WRONGURL', displayAjax);

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

Но чтобы действительно вывести ошибку только способ заключается в том, чтобы написать неправильный URL, в этом случае каждый браузер выдает ошибку.

Обработчики ошибок могут быть полезны, если вы устанавливаете пользовательские заголовки, устанавливаете responseType для буфера массива blob или чего-то еще …

Даже если вы передадите POSTAPAPAP в качестве метода, он не выдаст ошибку.

Даже если вы передадите ‘fdggdgilfdghfldj’ в качестве форм-данных, это не выдаст ошибку.

В первом случае ошибка находится внутри displayAjax() под this.statusText как Method not Allowed,

Во втором случае это просто работает. Вы должны проверить на стороне сервера, если вы передали правильные данные поста.

междоменный домен не разрешен, выдает ошибку автоматически.

В ответе об ошибке нет кодов ошибок.

Есть только this.type который установлен на ошибку.

Зачем добавлять обработчик ошибок, если вы полностью не можете контролировать ошибки?
Большинство ошибок возвращаются внутри этого в функции обратного вызова displayAjax(),

Итак: нет необходимости в проверке ошибок, если вы можете правильно скопировать и вставить URL. 😉

PS: В качестве первого теста я написал x (‘x’, displayAjax) …, и он полностью получил ответ … ??? Поэтому я проверил папку, в которой находится HTML, и там был файл с именем «x.xml». Так что даже если вы забудете расширение вашего файла, XMLHttpRequest 2 НАЙДЕТ ЕГО. Я смеюсь


Чтение файла синхронно

Не делай этого.

Если вы хотите на время заблокировать браузер, загрузите хороший большой .txt файл синхронный.

function omg(a, c){ // URL
c = new XMLHttpRequest;
c.open('GET', a, true);
c.send();
return c; // Or c.response
}

Теперь вы можете сделать

 var res = omg('thisIsGonnaBlockThePage.txt');

Нет другого способа сделать это не асинхронно. (Да, с циклом setTimeout … но серьезно?)

Другой момент … если вы работаете с API-интерфейсами, или просто с файлами собственного списка, или с чем угодно, вы всегда используете разные функции для каждого запроса …

Только если у вас есть страница, на которую вы загружаете всегда один и тот же XML / JSON или что-то еще, вам нужна только одна функция. В этом случае немного измените функцию Ajax и замените b своей специальной функцией.


Функции выше предназначены для базового использования.

Если вы хотите расширить функцию …

Да, ты можешь.

Я использую множество API, и одной из первых функций, которые я интегрирую в каждую HTML-страницу, является первая функция Ajax в этом ответе, только с GET …

Но вы можете многое сделать с XMLHttpRequest 2:

Я сделал менеджер загрузок (используя диапазоны с обеих сторон с помощью резюме, файлового ридера, файловой системы), различные конвертеры, изменяющие размер изображения, используя холст, заполнял базы данных веб-SQL с помощью base64images и многое другое … Но в этих случаях вы должны создать функцию только для этого цель … иногда вам нужны блоб, буферы массивов, вы можете установить заголовки, переопределить mimetype и многое другое …

Но вопрос здесь в том, как вернуть ответ Ajax … (я добавил простой способ.)

342

Это означает AngularJS, jQuery (с отсрочкой), замену (извлечение) собственного XHR, сохранение EmberJS, BackboneJS или любую библиотеку узлов, которая возвращает обещания.

Ваш код должен быть примерно таким:

function foo() {
var data;
// or $.get(...).then, or request(...).then, or query(...).then
fetch("/echo/json").then(function(response){
data = response.json();
});
return data;
}

var result = foo(); // result is always undefined no matter what.

Феликс Клинг отлично справился с написанием ответа для людей, использующих jQuery с обратными вызовами для AJAX. У меня есть ответ для родного XHR. Этот ответ предназначен для общего использования обещаний на веб-интерфейсе или на сервере.


Модель параллелизма JavaScript в браузере и на сервере с NodeJS / io.js асинхронный а также реактивный.

Всякий раз, когда вы вызываете метод, который возвращает обещание, then обработчики всегда выполняется асинхронно — то есть после код под ними, который не находится в .then обработчик.

Это значит, когда вы возвращаетесь data then определенный вами обработчик еще не выполнен Это, в свою очередь, означает, что возвращаемое вами значение не было правильно установлено во времени.

Вот простая аналогия для вопроса:

    function getFive(){
var data;
setTimeout(function(){ // set a timer for one second in the future
data = 5; // after a second, do this
}, 1000);
return data;
}
document.body.innerHTML = getFive(); // `undefined` here and not 5
276

Вы используете Ajax неправильно. Идея не в том, чтобы он что-либо возвращал, а в том, чтобы передать данные чему-то, что называется функцией обратного вызова, которая обрабатывает данные.

То есть:

function handleData( responseData ) {

// Do what you want with the data
console.log(responseData);
}

$.ajax({
url: "hi.php",
...
success: function ( data, status, XHR ) {
handleData(data);
}
});

Возврат чего-либо в обработчик отправки ничего не сделает. Вместо этого вы должны либо передать данные, либо сделать то, что вы хотите, непосредственно внутри функции успеха.

217

Самое простое решение — создать функцию JavaScript и вызвать ее для Ajax. success Перезвоните.

function callServerAsync(){
$.ajax({
url: '...',
success: function(response) {

successCallback(response);
}
});
}

function successCallback(responseObj){
// Do something like read the response and show data
alert(JSON.stringify(responseObj)); // Only applicable to JSON response
}

function foo(callback) {

$.ajax({
url: '...',
success: function(response) {
return callback(null, response);
}
});
}

var result = foo(function(err, result){
if (!err)
console.log(result);
});
206

Я отвечу ужасно выглядящим, нарисованным от руки комиксом. Второе изображение является причиной, почему result является undefined в вашем примере кода.

введите описание изображения здесь

178

Angular1

Для людей, которые используют AngularJS, может справиться с этой ситуацией, используя Promises,

Вот это говорит,

Обещания могут быть использованы для удаления вложенных асинхронных функций и позволяют объединить несколько функций в цепочку.

Вы можете найти хорошее объяснение Вот также.

Пример найден в документы упомянуто ниже.

  promiseB = promiseA.then(
function onSuccess(result) {
return result + 1;
}
,function onError(err) {
//Handle error
}
);

// promiseB will be resolved immediately after promiseA is resolved
// and its value will be the result of promiseA incremented by 1.

Angular2 и позже

В Angular2 со взглядом на следующий пример, но его рекомендуемые использовать Observables с Angular2,

 search(term: string) {
return this.http
.get(`https://api.spotify.com/v1/search?q=${term}&type=artist`)
.map((response) => response.json())
.toPromise();

}

Вы можете потреблять это таким образом,

search() {
this.searchService.search(this.searchField.value)
.then((result) => {
this.result = result.artists.items;
})
.catch((error) => console.error(error));
}

Увидеть оригинал разместить здесь. Но Typescript не поддерживает родной es6 обещания, если вы хотите использовать его, вам может понадобиться плагин для этого.

Дополнительно вот обещания спекуляция определите здесь.

131
По вопросам рекламы [email protected]