Вопрос был:
Как вернуть ответ от асинхронного вызова?
, который может быть интерпретирован как:
Как сделать синхронный асинхронный код синхронным?
Решение будет состоять в том, чтобы избежать обратных вызовов и использовать комбинацию Promises и async / await.
Я хотел бы привести пример для запроса Ajax.
(Хотя он может быть записан в Javascript, я предпочитаю писать его на Python и компилировать его в Javascript, используя Transcrypt . Это будет достаточно ясно.)
Позволяет сначала включить использование JQuery, чтобы
$
был доступен какS
:__pragma__ ('alias', 'S', '$')
Определить функцию, которая возвращает Promise, в этом случае вызов Ajax:
def read(url: str): deferred = S.Deferred() S.ajax({'type': "POST", 'url': url, 'data': { }, 'success': lambda d: deferred.resolve(d), 'error': lambda e: deferred.reject(e) }) return deferred.promise()
Использовать асинхронный код, как если бы он был синхронным:
async def readALot(): try: result1 = await read("url_1") result2 = await read("url_2") except Exception: console.warn("Reading a lot failed")
Если вы используете HTML5 и JSF 2.2+, укажите его как атрибут passthrough .
<html ... xmlns:a="http://xmlns.jcp.org/jsf/passthrough">
<h:inputTextarea value="#{bean.text}" a:maxlength="2000" />
Если вы используете HTML5, но не JSF 2.2, используйте OmniFaces Html5RenderKit
, чтобы распознавать новые атрибуты HTML5 в JSF 2.0 / 2.1.
<h:inputTextarea value="#{bean.text}" maxlength="2000" />
Если вы используете HTML4, то он уже не поддерживается самим HTML. Он поддерживается только на элементе <input>
, а не на элементе <textarea>
. Вот почему в представлении JSF этого элемента HTML нет такого атрибута. Вам необходимо решить это требование на стороне клиента, используя JS и / или на стороне сервера, используя JSF. JS позволяет мгновенно проверять длину и игнорировать все остальные символы. JSF позволяет также проверить его на случай отказа клиента или взлома JS-кода. Лучше всего было бы сочетать оба.
Предполагая, что у вас есть
<h:inputTextarea value="#{bean.text}" styleClass="max">
<f:validateLength maximum="2000" />
</h:inputTextarea>
, вот как вы могли бы сделать jQuery
$('textarea.max').keyup(function() {
var $textarea = $(this);
var max = 2000;
if ($textarea.val().length > max) {
$textarea.val($textarea.val().substr(0, max));
}
});
<h:inputTextarea required="true" cols="50" rows="5" id=”aboutMe” value="#{person.aboutMe}”>
<f:validateLength maximum="400" minimum="20"/>
</h:inputTextarea>
Ответ BalusC хорош, но, пожалуйста, будьте осторожны, чтобы проверщик JSF, вызванный с помощью f:validateLength maximum="2000" />
, будет считать новые строковые символы дважды, тогда как $textarea.val().length
будет считать их только один раз. Вам нужно будет удвоить количество повторов новой строки в вашем проверяющем JavaScript, если вы хотите, чтобы два валидатора возвращали одни и те же результаты для многострочных входов.
Примером этой проблемы был бы вход "Hello\nWorld"
в вашей текстовой области, где\n - это разрыв строки. Это будет считаться 12 символами с помощью проверки подлинности JSF, но $textarea.val().length
вернется только 11. Это расхождение, очевидно, ухудшится, если вы позволите пользователю ввести несколько абзацев.
Хотя не о том же субъект, первые пара абзацев этой статьи объясняют поведение JavaScript. Также есть некоторые комментарии к этой точной проблеме, которая может быть полезной.