f2
не обязательно знает, что его вызывают из f1
, верно? Вы могли бы когда-нибудь сделать рефакторинг для f1
call f3
, который затем вызывает f2
. В этот момент было бы неясно, хотите ли вы, чтобы f2
принудительно вернул f3
или f1
. В целом, языки ожидают, что f2
написано , написанное так, чтобы не знать точно, где оно вызывается , или иметь глубокий контроль над тем, что происходит в вызывающем методе: возвращаемое значение f2
должно заменить вызов f2
без дальнейшего контроля над выполнением f1
.
Типичными способами решения этой проблемы являются throw
исключение (которое go поднимает стек до точки где это поймано, и было бы особенно разумно, учитывая, что это кажется ошибкой) или return
значение дозорного, которое указывает, что вы должны вернуться рано. Звучит так, что ложные значения, такие как false
или null
, являются хорошими кандидатами, но вы уже указали, что этот стандартный подход не подходит для ваших нужд.
Однако другой метод, который вы можете использовать, это продолжение с передачей style , что я предлагаю, потому что кажется, что вы можете отредактировать f2
для получения обратного вызова (из которых продолжение является специальной формой ). Это позволяет f1
делегировать управление f2
, за исключением того, что он вызывает обратный вызов в случае успеха, а не сбоя. Это гораздо чаще встречается в асинхронных случаях, таких как Promises, чем в вашем синхронном случае, но это может обеспечить гибкость, необходимую вам в синхронном случае, и позволяет задержать вызов continuation
, если f2
становится асинхронным. Это также позволяет f1
выбирать, следует ли возвращаться немедленно или нет, и позволяет гипотетически рефакторированному f3
принимать и передавать продолжение f1
или передавать свое собственное (потенциально вызывая продолжение f1
после дальнейшая обработка).
function f1() {
return f2(a => {
/* the rest of f1 that consumes a */
return ...
});
}
function f2(continuation: (a: TypeOfA) => typeOfF1) {
if (error) {
// f1 returns this immediately, and never has its continuation called.
return ERROR_VALUE;
}
// calculate return value
return continuation(a);
}