Во-первых, это очень специфический случай неправильной реализации намеренного преобразования асинхронного вызова в очень синхронную кодовую базу длиной в несколько тысяч строк, и время в настоящее время не позволяет вносить изменения в «делать». это правильно. " Это ранит каждую клеточку моего существа, но реальность и идеалы часто не совпадают. Я знаю это отстой.
Хорошо, что с дороги, как мне сделать так, чтобы я мог:
function doSomething() {
var data;
function callBack(d) {
data = d;
}
myAsynchronousCall(param1, callBack);
// block here and return data when the callback is finished
return data;
}
Все примеры (или их отсутствие) используют библиотеки и / или компиляторы, которые не подходят для этого решения. Мне нужен конкретный пример того, как заставить его блокироваться (например, НЕ оставлять функцию doSomething до тех пор, пока не будет вызван обратный вызов) БЕЗ зависания интерфейса. Если такое возможно в JS.
javascript
asynchronous
Роберт С. Барт
источник
источник
Ответы:
ХОРОШО. но вы должны действительно сделать это правильно ... или что-то
Нет, невозможно заблокировать работающий JavaScript без блокировки пользовательского интерфейса.
Из-за недостатка информации сложно предложить решение, но один из вариантов может заключаться в том, чтобы вызывающая функция провела опрос для проверки глобальной переменной, а затем установила обратный вызов
data
в глобальную.Все это предполагает, что вы можете изменить
doSomething()
. Я не знаю, есть ли это в карточках.Если это можно изменить, тогда я не знаю, почему бы вам не передать обратный вызов для вызова
doSomething()
из другого обратного вызова, но я лучше остановлюсь, прежде чем у меня возникнут проблемы. ;)Ох, какого черта. Вы привели пример, который предполагает, что это можно сделать правильно, поэтому я собираюсь показать это решение ...
Поскольку ваш пример включает в себя обратный вызов, который передается асинхронному вызову, правильным способом будет передать функцию
doSomething()
которая будет вызвана из обратного вызова.Конечно, если это единственное, что делает обратный вызов, вы бы просто передали
func
напрямую ...источник
callback
функциюmyAsynchronousCall
функции, которая выполняет асинхронные операции и вызывает обратный вызов, когда завершается. Вот демо.Асинхронные функции , функция в ES2017 , делают асинхронный код синхронизированным с помощью обещаний (особая форма асинхронного кода) и
await
ключевого слова. Также обратите внимание на примеры кода ниже ключевого словаasync
передfunction
ключевым словом, которое обозначает функцию async / await.await
Ключевое слово не будет работать , не будучи в функции предварительного фиксированной сasync
ключевым словом. Поскольку в настоящее время нет исключения из этого, это означает, что не будет работать ожидание верхнего уровня (ожидание верхнего уровня означает ожидание вне какой-либо функции). Хотя есть предложение на высшем уровнеawait
.ES2017 был утвержден (то есть окончательно доработан) как стандарт для JavaScript 27 июня 2017 года. Async await может уже работать в вашем браузере, но если нет, вы все равно можете использовать эту функциональность с помощью транспортера javascript, такого как babel или traceur . Chrome 55 имеет полную поддержку асинхронных функций. Так что если у вас более новый браузер, вы можете попробовать код ниже.
См . Таблицу совместимости с кангаксом es2017 для совместимости с браузером.
Вот пример вызываемой функции асинхронного ожидания,
doAsync
которая берет три паузы в одну секунду и печатает разницу во времени после каждой паузы от времени начала:Когда ключевое слово await помещается перед значением обещания (в этом случае значением обещания является значение, возвращаемое функцией doSomethingAsync), ключевое слово await приостанавливает выполнение вызова функции, но не приостанавливает другие функции и продолжает выполнение другого кода до разрешения обещания. После того, как обещание разрешено, оно развернет значение обещания, и вы можете думать, что выражение ожидания и обещания теперь заменяется этим развернутым значением.
Итак, поскольку await просто делает паузу, ждет, а затем разворачивает значение перед выполнением остальной части строки, вы можете использовать его для циклов и внутренних вызовов функций, как в примере ниже, который собирает ожидаемые во времени различия в массиве и распечатывает массив.
Сама асинхронная функция возвращает обещание, так что вы можете использовать его как обещание с цепочкой, как я делал выше или в другой функции асинхронного ожидания.
Приведенная выше функция будет ожидать каждого ответа перед отправкой другого запроса, если вы хотите отправлять запросы одновременно, вы можете использовать Promise.all .
Если обещание может быть отклонено, вы можете заключить его в попытку catch или пропустить попытку try и позволить ошибке распространиться на вызов catch функций async / await. Вы должны быть осторожны, чтобы не оставлять ошибки в обещаниях необработанными, особенно в Node.js. Ниже приведены некоторые примеры, показывающие, как работают ошибки.
Если вы идете сюда то увидите готовые предложения для будущих версий ECMAScript.
Альтернативой этому, которая может использоваться только с ES2015 (ES6), является использование специальной функции, которая оборачивает функцию генератора. Функции генератора имеют ключевое слово yield, которое можно использовать для репликации ключевого слова await с окружающей функцией. Ключевое слово yield и функция генератора имеют гораздо более общее назначение и могут выполнять гораздо больше функций, чем просто функция асинхронного ожидания. Если вы хотите , функция упаковщик генератор , который может быть использован для репликации асинхронного ждать , я хотел бы проверить co.js . Кстати, функция co, очень похожая на функции асинхронного ожидания, возвращает обещание. Честно говоря, на данный момент совместимость браузера примерно одинакова как для функций генератора, так и для асинхронных функций, поэтому, если вы просто хотите использовать функцию асинхронного ожидания, вы должны использовать функции Async без co.js.
Поддержка браузеров в настоящее время довольно хороша для функций Async (по состоянию на 2017 год) во всех основных современных браузерах (Chrome, Safari и Edge), кроме IE.
источник
Посмотрите на Обещания JQuery:
http://api.jquery.com/promise/
http://api.jquery.com/jQuery.when/
http://api.jquery.com/deferred.promise/
Рефакторинг кода:
источник
dfd.notify(data)
доdfd.resolve(data)
Есть один хороший обходной путь на http://taskjs.org/
Он использует генераторы, которые являются новыми для JavaScript. Так что в настоящее время он не реализован большинством браузеров. Я проверил это в Firefox, и для меня это хороший способ обернуть асинхронную функцию.
Вот пример кода из проекта GitHub
источник
Вы можете заставить асинхронный JavaScript в NodeJS быть синхронным с sync-rpc .
Тем не менее, он определенно заморозит ваш пользовательский интерфейс, поэтому я все еще скептически отношусь к тому, возможно ли использовать ярлык, который вам нужен. Невозможно приостановить единый поток в JavaScript, даже если NodeJS позволяет вам иногда блокировать его. Никакие обратные вызовы, события или что-либо асинхронное вообще не смогут обрабатываться, пока ваше обещание не разрешится. Поэтому, если вы, читатель, не столкнетесь с неизбежной ситуацией, такой как OP (или, в моем случае, не пишете прославленный скрипт оболочки без обратных вызовов, событий и т. Д.), НЕ ДЕЛАЙТЕ ЭТОГО!
Но вот как вы можете это сделать:
./calling-file.js
./my-asynchronous-call.js
ОГРАНИЧЕНИЯ:
И то и другое является следствием того, как
sync-rpc
это реализовано, а именно злоупотреблениемrequire('child_process').spawnSync
:JSON.stringify
будут входить и выходить , поэтому функции и неперечислимые свойства, такие как цепочки прототипов, будут потеряны.источник
Вы также можете конвертировать его в обратные вызовы.
источник
То, что вы хотите, на самом деле возможно сейчас. Если вы можете запустить асинхронный код в сервисном работнике и синхронный код в веб-работнике, тогда вы можете попросить веб-работника отправить синхронный XHR сервисному работнику, и пока работник сервиса выполняет асинхронные операции, веб-работник нить будет ждать. Это не очень хороший подход, но он может сработать.
источник
Идея, которую вы надеетесь достичь, станет возможной, если вы немного измените требование
Приведенный ниже код возможен, если ваша среда выполнения поддерживает спецификацию ES6.
Подробнее об асинхронных функциях
источник
SyntaxError: await is only valid in async functions and async generators
. Не говоря уже о том, что param1 не определен (и даже не используется).