Ожидание завершения асинхронной задачи
Я взаимодействую с сторонней библиотекой JavaScript, где некоторые вызовы функций являются асинхронными. Вместо того, чтобы интегрировать асинхронную логику в моё приложение, я решил написать синхронные обертки для этих асинхронных вызовов. Я понимаю, что это ужасный дизайн, но это демонстрационный проект, который, скорее всего, будет переписан. Мне нужно показать команде концепцию, а производительностью на данном этапе особо не переживать.
Вот что я хочу сделать:
function sync_call(input) {
var value;
// Предполагаем, что асинхронный вызов всегда успешен
async_call(input, function(result) {value = result;} );
return value;
}
Я пробовал использовать jQuery's deferred и promise, но, похоже, они ориентированы на асинхронный дизайн. Я хочу использовать синхронную модель в моём коде.
2 ответ(ов)
Вместо того чтобы возвращать значение в функции sync_call()
, вы можете вызывать другую функцию непосредственно в вашем коллбэке. Это позволит вам работать с результатом асинхронного вызова сразу после его завершения, не дожидаясь возвращения значения. Примерно так:
function sync_call(input) {
// Предположим, что асинхронный вызов всегда успешен
async_call(input, function(result) {
use_value(result); // Вызываем use_value сразу, когда получили результат
});
}
Таким образом, вы убираете необходимость в переменной value
, а вся логика обработки результата остается в коллбэке. Это более идиоматичный подход в JavaScript, который лучше справляется с асинхронностью.
Вот работающий пример, как это сделать:
function testAsync(){
return new Promise((resolve, reject) => {
// Здесь должна быть реализована наша функция
setTimeout(() => {
console.log("Привет изнутри функции testAsync");
resolve();
}, 5000);
});
}
async function callerFun(){
console.log("Вызов");
await testAsync();
console.log("После ожидания");
}
callerFun();
Этот код выводит:
Вызов
Привет изнутри функции testAsync
После ожидания
Чтобы сделать реализацию более полной, стоит добавить обработку ошибок (обработку случая с reject()). Вот пример с добавлением обработки ошибок:
function testAsync(){
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log("Привет изнутри функции testAsync");
// Для теста выбросим ошибку
const errorOccurred = false; // замените на true, чтобы сгенерировать ошибку
if (errorOccurred) {
reject(new Error("Произошла ошибка"));
} else {
resolve();
}
}, 5000);
});
}
async function callerFun(){
console.log("Вызов");
try {
await testAsync();
console.log("После ожидания");
} catch (error) {
console.error("Ошибка:", error.message);
}
}
callerFun();
Теперь, если в функции testAsync
произойдет ошибка и вызовется reject
, она будет поймана в блоке catch
, и мы получим соответствующее сообщение об ошибке.
Для других примеров, смотрите здесь: https://www.delftstack.com/howto/javascript/javascript-wait-for-function-to-finish/
Как загружать файлы асинхронно с помощью jQuery?
Как заставить jQuery выполнять синхронный запрос Ajax вместо асинхронного?
Прокрутка к элементу с использованием jQuery
Как определить нажатие клавиши Esc?
Как выполнить код после сброса HTML-формы с помощью jQuery?