На основании ваших комментариев о том, что вы ждете сообщений от сервера, выясняется, что вы пытаетесь решить проблему X / Y .Поэтому я собираюсь ответить на вопрос « как мне ждать сообщений сервера » вместо ожидания изменения глобальной переменной.
Если ваш сетевой API принимает обратный вызов
Множество сетевых API, таких как XMLHttpRequest и узла Http.request () , основаны на обратном вызове.Если используемый вами API является обратным вызовом или основан на событиях, то вы можете сделать что-то вроде этого:
function myFunctionToFetchFromServer () {
// example is jQuery's ajax but it can easily be replaced with other API
return new Promise(function (resolve, reject) {
$.ajax('http://some.server/somewhere', {
success: resolve,
error: reject
});
});
}
async function waiting (intro){
var result = await myFunctionToFetchFromServer();
console.log(intro + result);
}
Если ваш сетевой API основан на обещаниях
Если, с другой стороны, вы используетеБолее современный сетевой API, основанный на обещаниях, такой как fetch () , вы можете просто дождаться обещания:
function myFunctionToFetchFromServer () {
return fetch('http://some.server/somewhere');
}
async function waiting (intro){
var result = await myFunctionToFetchFromServer();
console.log(intro + result);
}
Отключение доступа к сети от вашего обработчика событий
Примечаниечто следующее - это только мое мнение , но это также нормальная стандартная практика в сообществе javascript :
В любом случае выше, когда у вас есть обещание, можно отделитьВаш сетевой API формирует ваш waiting()
обработчик событий.Вам просто нужно сохранить обещание в другом месте.Ответ Эверта показывает, как вы можете это сделать.
Однако, по моему не столь скромному мнению, вы не должны этого делать .В проектах значительных размеров это приводит к трудностям в поиске источника, где происходит изменение состояния.Это то, что мы сделали в 90-х и начале 2000-х годов с помощью JavaScript.В нашем коде было много events
, таких как onChange
и onReady
или onData
вместо обратных вызовов, переданных в качестве параметров функции.В результате иногда требуется много времени, чтобы выяснить, какой код вызывает какое событие.
Параметры обратного вызова и обещания вынуждают генератор событий находиться в том же месте в коде, что и получатель события:
let this_variable_consumes_result_of_a_promise = await generate_a_promise();
this_function_generate_async_event((consume_async_result) => { /* ... */ });
Судя по формулировке вашего вопроса, вы хотите сделать это вместо этого;
.. где-то в вашем коде:
this_function_generate_async_event(() => { set_global_state() });
... где-то ещев вашем коде:
let this_variable_consumes_result_of_a_promise = await global_state();
Я бы посчитал это анти-паттерном .
Вызов асинхронных функций в конструкторах классов
Это не толькоанти-шаблон, но невозможность (как вы, несомненно, обнаружили, когда обнаружите, что не можете вернуть асинхронный результат).
Однако существуют шаблоны проектирования, которые могут обойти это.Ниже приведен пример предоставления соединения с базой данных, которое создается асинхронно:
class MyClass {
constructor () {
// constructor logic
}
db () {
if (this.connection) {
return Promise.resolve(this.connection);
}
else {
return new Promise (function (resolve, reject) {
createDbConnection(function (error, conn) {
if (error) {
reject(error);
}
else {
this.connection = conn; // cache the connection
resolve(this.connection);
}
});
});
}
}
}
Использование:
const myObj = new MyClass();
async function waiting (intro){
const db = await myObj.db();
db.doSomething(); // you can now use the database connection.
}
Подробнее об асинхронных конструкторах можно прочитать в моем ответе на этот другой вопрос: Конструктор асинхронных / ожидающих классов