2015-05-07 3 views
3

У меня есть целая цепочка функций на объекте. Например:Вырыв из цепочки функций

var obj = {}; 
obj.a = function(){ 
    console.log('in a'); 
    return this; 
}; 


obj.b = function(){ 
    console.log('in b'); 
    return this; 
}; 

obj.c = function(){ 
    console.log('in c'); 
    return this; 
}; 

obj.a().b().c(); 

Очевидно, что результат, когда я смотрю на консоли:

in a 
in b 
in c 

Но как бы я вырваться из этого так, что a и b выполнить, но c никогда не будет достигнуто?

+0

Если вы напишете 'c()', это будет выполнено. То, что вы могли бы сделать, это заменить возвращаемое значение 'b' на' {c: function() {}} ', но это отвратительно. –

+0

@OmarElawady, который выкинул бы ошибку – Mark

+0

Вы не можете выйти из функции, если вы ее запустили. Функция заканчивается в инструкции return или в конце ее тела. –

ответ

2

Очевидным ответом является «просто не называть c», но я думаю, что по какой-то причине это не вариант.

В этом случае вы можете взломать его, выбросив ошибку с одного из вызовов функций до c, но я бы не рекомендовал его. Исключение составляют обработка ошибок, а не управление потоком [*].

var obj = {}; 
obj.a = function(){ 
    console.log('in a'); 
    return this; 
}; 


obj.b = function(){ 
    console.log('in b'); 
    if(shouldBreak) { 
     throw new Error('decided to break'); 
    } 

    return this; 
}; 

obj.c = function(){ 
    console.log('in c'); 
    return this; 
}; 

try { 
    obj.a().b().c(); 
} catch { 
    console.log('broke early') 
} 

[*] unless you're into Python

-1

Установить поле класса в a() или b(), проверяется при c().

0

Просто добавьте переменную вне своих методов, скажем, что она называется флагом, по умолчанию используется значение true.

Любой метод, который вы не хотите продолжать, после того, как этот флаг установлен на false. Затем проверьте флаг перед возвратом.

Так что-то вроде:

var flag = true 

function b() { 
    flag = false 
    return this 
} 

function c() { 
    return flag ? this : null 
} 
0

Самый простой способ это так же, как вы вырваться из любого вызова функции: выдаст ошибку.

var obj = { 
    someCondition: false, 

    a: function() { 
     return this; 
    }, 

    b: function() { 
     if (!this.someCondition) { 
      var error = new Error("A message"); 
      error.name = "SomeConditionError"; 
      throw error; 
     } 

     return this; 
    }, 

    c: function() { 
     return this; 
    } 
}; 

А затем вызовите методы и обработайте ошибку.

try { 
    obj 
     .a() 
     .b() // throws a "SomeConditionError" here 
     .c(); 
} 
catch (error) { 
    if (error.name == "SomeConditionError") { 
     // gracefully handle "SomeConditionError" 
    } 
    else { 
     // rethrow errors you don't know how to handle gracefully 
     throw error; 
    } 
} 

Единственное, чего вы хотите избежать, это using exceptions for flow control.

Если вам нужно вызвать obj.a() затем obj.b(), но затем условно назвать obj.c() то вызывающий код должен справиться с этим:

obj.a().b(); 

if (someCondition) { 
    // Assign to "obj" just in case obj.c() returns a different object 
    obj = obj.c(); 
} 

Он чувствует себя уродливой кода (и это несколько), но сообщает, что любые ошибки, вызванные этими вызовами метода, являются катастрофическими, показывая ошибки остановки. Если у вас есть сложная операция, которая включает в себя несколько вызовов метода на одном объекте или нескольких объектов, считают инкапсулирования, что в «command»:

function DoSomethingCommand(obj) { 
    this.obj = obj; 
} 

DoSomethingCommand.prototype = { 
    constructor: DoSomethingCommand, 

    execute: function() { 
     this.obj.a().b(); 

     if (someCondition) { 
      this.obj = this.obj.c(); 
     } 
    } 
}; 

С точки зрения вызывающего кода, это только простой вызов execute() к начинайте очень сложный процесс:

var command = new DoSomethingCommand(obj); 

command.execute(); 
Смежные вопросы