Как вернуться из функции, вызвавшей текущую функцию? - PullRequest
0 голосов
/ 17 апреля 2020

Допустим, у меня есть две функции f1() и f2(). Чтобы служить своей цели, f1() необходимо вернуть истинное значение. f1() вызывает f2() и, исходя из условий, я хочу, чтобы f2() либо возвращал истинное значение, либо возвращал напрямую из f1() (вызывающая функция).

//f1()
function f1() {
    const a = f2();
    ...
    ...
    return ...
}

//f2()
function f2() {
    ...
    if(error) {
        // I want to execute return on f1()'s scope here
    }
    ...
    return ...
}

Мой подход:

//f2()
function f2(callback: () => void) {
    ...
    if(error) {
        callback();
    }
    ...
    return ...
}

//f1()
function f1() {
    const a = f2(() => {return...});
    ...
    ...
    return ...
}

К сожалению, он только возвращает значения в f2(), как и ожидалось.

Как решить эту проблему? Пожалуйста, не предлагайте другие вещи, такие как возврат нуля из f2() в блоке if и возврат в f1() в зависимости от условия. Я хочу, чтобы f2() прекратил выполнение f1() по моим собственным причинам.

Спасибо.

1 Ответ

0 голосов
/ 17 апреля 2020

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);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...