如何退出函数 cascade/chain?

How do I exit a function cascade/chain?

如果您使用 return this 的函数创建一个对象,您可以创建之前调用的函数链并创建级联函数调用:

var i = {
  foo: function () {
    // Something here...
    return this;
  },

  bar: function () {
    // Something here...
    return this;
  }
};

i.foo().bar().foo()

但是,如果在 bar 中发生错误并且我不想在那种情况下调用 foo 怎么办?如何打破级联?

如果可能的话,我想避免 try/catch 语句。

也许不是您想要的,但 Promises 非常适合链接和错误处理:

var i = {
   count: 0,
  foo: function () {
    // Something here...
    this.count++;
    console.log('foo');
    return  this.count < 4 ? 
      Promise.resolve(this) :
      Promise.reject(new Error('Count too high!'));
  },

  bar: function () {
    // Something here...
    this.count++;
    console.log('bar');
    return  this.count < 4 ? 
     Promise.resolve(this) :
        Promise.reject(new Error('Count too high! Count is ' + this.count));
  }
};


i.foo() // first
  .then(i => i.bar()) // second
  .then(i => i.foo()) // third
  .then(i => i.bar()) // too much!
  .then(i => i.whatIsThis()) // will not run
  .then(i => i.whatIsThis()) // will not run
  .catch(error => console.log(error.message));

可以 return 一个新的 i 的空实例,然后在错误 return 一个空对象时:

class Chainable {
 constructor(data){
   this.data = data;
 }
 foo (foo) {
  //if an error occured
  if(foo == 10) return new Chainable();
  // Something here...
  return new Chainable(this.data + foo);
 },
 bar () {
  //if were in an error, fail silently
  if(!this.data) return this;
  // Something here...
  return this;
 }
}

(new Chainable(1))
  .foo(5).bar().bar().data // 6
(new Chainable(1))
  .foo(10).bar().bar().data //undefined

好吧,一件直截了当的事情是,如果你想在没有 try/catch 的情况下处理这种情况,你必须在你的函数中加入 if 条件,显然你必须 return一些东西,这样你就可以在那个上下文而不是异常上执行更多的功能。因此,尝试在一个对象中创建所有功能,并仅在有人扩展时才允许执行您的功能逻辑。失败时 return 基础,否则 return 当前对象。这样您就可以避免每次都创建对象。

示例: 让我们考虑一下您有 BaseService 定义了所有功能,并在其上放置一个层以进一步扩展,因此您可以采用这种模式:

foo: function() {
    if(<function foo does not belongs to this>) {
        .......
        .......
        if(<on logical failure>) {
            return this.__proto__;
        }
        .......
        .......
    }
    return this;
}

这是一个工作片段:

function BaseService() {
    var dataBucket = [13, 50, 45, 57, 95];

    this.foo = function() {
        if (Object.values(this).indexOf(arguments.callee) === -1) {
            console.log('processing foo');
        }
        return this;
    }
    this.bar = function() {
        if (Object.values(this).indexOf(arguments.callee) === -1) {
            console.log('processing bar');
        }
        return this;
    }
    this.processValIfExists = function(val) {
        if (Object.values(this).indexOf(arguments.callee) === -1) {
            console.log('processing processValIfExists');
            if (dataBucket.indexOf(val) > -1) {
                //process the value further
            } else {
                return this.__proto__;
            }
        }
        return this;
    }
};

//define the extended service, you can add further
//functionalities here. eg: createing the dataBucket here from args 
function WrapperService() {};

WrapperService.prototype = new BaseService(); // just extend from any service and use

var svc = new WrapperService();

console.log('----------Executes All-----------');
svc.foo().bar().processValIfExists(95).foo().bar();


console.log('----------Executes upto processValIfExists-----------');
svc.foo().bar().processValIfExists(100).foo().bar();

请注意,这只是我想到的一种不同的方法,为了检查当前的调用方法,我尝试使代码通用,而不是检查它的 WrapperService 实例是否在 BaseService 函数以避免代码耦合,也可以从任何其他服务扩展。