У меня есть такая функция:
let maybeRun = function (cb: Function, allow: boolean, ctx: object = window) {
return function () {
if (!allow) return;
cb.call(ctx, ...arguments);
// cb.apply(ctx, arguments);
};
};
В случае, если cb
является синхронным, проблем нет, но как мне поступить в случае, если cb
возвращает обещание (асинхронно)?
let cb = async ()=> {...};
let foo = maybeRun(cb, true);
await foo()
Я хочу, чтобы возвращаемая функция foo
имела такое же поведение, как cb
(синхронная или асинхронная).
Вам вообще не нужно делать ничего особенного; функция async
просто возвращает обещание, как и любое другое возвращаемое значение.
Но обратите внимание, что вам не хватает return
в вашей функции-оболочке. Ваша функция отбрасывала любое полученное возвращаемое значение (включая обещание).
let maybeRun = function (cb: Function, allow: boolean, ctx: object = window) {
return function () {
if (!allow) return; // *** See note below
return cb.call(ctx, ...arguments);
// −−−−−^^^^^^
};
};
Одна проблема заключается в том, что ваша оболочка теперь иногда возвращает обещание, а в другое время - нет. Нет ничего (стандартного), что вы можете сделать, чтобы посмотреть на cb
(без его вызова), чтобы увидеть, возвращает ли он обещание, так что это может быть просто ограничением, с которым вам придется иметь дело. (Вы могу вынюхиваете, является ли это async
функцией, но вы не можете знать, является ли это не async
функцией, которая возвращает обещание.)
В комментарии вы сказали:
i didn't write a return because the wrapped functions i need this function for have no returns
Это меняет ситуацию для вашего конкретного варианта использования: вы просто используете await
при вызове функции:
let maybeRun = function (cb: Function, allow: boolean, ctx: object = window) {
return async function () {
// −−−−−−−−^^^^^
if (!allow) return;
await cb.call(ctx, ...arguments);
// −−−−−^^^^^
};
};
Теперь ваша функция (будучи async
) всегда возвращает обещание, а в случаях, когда cb
возвращает обещание (либо явно, либо потому, что это функция async
), ваша функция будет ждать, пока это обещание будет выполнено, прежде чем вернуться, но не будет возвращать значение исполнения.
Обратите внимание, что даже с этим изменением cb
вызывается синхронно, когда вы вызываете функцию-оболочку, полученную из maybeRun
. Функция async
работает синхронно до тех пор, пока ей не придется чего-то ждать в первый раз. Если cb
является синхронным, он будет запущен во время этого начального синхронного выполнения оболочки.
большое спасибо), я не писал возврат, потому что обернутые функции, для которых мне нужна эта функция, не возвращают, еще раз спасибо (:
@modex98 - А, это меняет дело. Я обновлю.
Я уверен, что вы все равно можете написать перегрузки, чтобы различать синхронные/асинхронные обратные вызовы.
О, я думал, мы говорим о типах, хе-хе ?
@catgirlkelly - Боже мой. Я полностью прочитал за типами и тег [typescript]. Теперь я должен пересмотреть ответ снова. ;-D О, подождите, нет, я не знаю, потому что даже если бы мы могли писать перегрузки, нам все равно пришлось бы основывать реализацию на значении времени выполнения того, что она получила, и мы не можем обнаружить функцию, которая явно возвращает обещание (включая переданную функцию async
). Тем не менее, ничего себе, когда я читаю сразу после типов. о_О
Нет ли внутреннего скрытого объекта AsyncFunction, похожего на функцию? Я помню, как сталкивался с этим в node.js. То же самое с AsyncGeneratorFunction и GeneratorFunction. Довольно дурацкая проклятая штука.
@catgirlkelly — есть GeneratorFunction
и AsyncGeneratorFunction
, но речь идет о более общих параметрах типа, потому что в них есть нечто большее, чем базовые функции. Но, несмотря на это, эта информация о типе не будет у функции реализации во время выполнения, которая ей понадобится, если мы собираемся основывать решение на том, возвращать ли обещание на ее основе.
Await ничего не делает с non-thenables, поэтому вы можете просто использовать
await cb(...)
.