如何退出功能级联/链?

时间:2017-08-31 19:09:38

标签: javascript chaining

如果创建一个包含返回this的函数的对象,则可以创建一个先前调用的函数链并创建一系列函数调用:

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

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

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

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

如果可能的话,我想避免try/catch陈述。

3 个答案:

答案 0 :(得分:1)

可以返回一个新的空实例i,然后在错误时返回一个空的obect:

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

答案 1 :(得分:1)

好的,所以一个直截了当的事情就是如果你想要处理没有try/catch的情况,你必须把if条件放在你的函数中,显然你必须返回一些东西,以便你可以进一步执行在该上下文上起作用而不是异常。因此,尝试在对象中创建所有功能,并且只有在有人扩展时才允许执行您的功能逻辑。并且在你的失败时返回基数,否则返回当前对象。在这种情况下,您可以避免每次都创建对象。

实施例: 让我们考虑你已经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();

请注意,它只是我想到的一种不同的方法,并检查当前的调用方法,我试图使代码通用,而不是检查WrapperServiceBaseService的实例是否为String hostName = "localhost"; String sqlInstanceName = "CURSEOFDARKNESS"; String database = "Hearthstone"; String integrated = "integratedSecurity=true"; return getSQLServerConnection_SQLJDBC(hostName, sqlInstanceName, database, integrated); } private static Connection getSQLServerConnection_SQLJDBC(String hostName, String sqlInstanceName, String database, String integrated) throws ClassNotFoundException, SQLException { Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver"); //i think problem is here but i dont know String connectionURL = "jdbc:sqlserver://" + hostName + ":1433" + ";instanceName=" + sqlInstanceName + ";databaseName=" + database + ";" + integrated; Connection conn = DriverManager.getConnection(connectionURL); return conn; 函数以避免代码耦合,也可以从任何其他服务扩展。

答案 2 :(得分:0)

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

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));