使用循环创建对象链接

时间:2019-03-03 15:43:24

标签: javascript knex.js

有没有一种方法可以从循环中创建链接的对象? 例如输入:

["table1","table2","table3"]

输出:

  db
  .select(fields)
  .from(table)
  .innerJoin("table1")
  .innerJoin("table2")
  .innerJoin("table3")

另一个输入:

 ["table1","table2","table3","table4","table5"]

输出:

  db
  .select(fields)
  .from(table)
  .innerJoin("table1")
  .innerJoin("table2")
  .innerJoin("table3")
  .innerJoin("table4")
  .innerJoin("table5")

现在,除了使用eval之外,我不知道该怎么做。我不希望这样做。

我需要使用knex联接多个表,因此,如果有其他方法,我将非常高兴:)

2 个答案:

答案 0 :(得分:2)

链接的工作方式是,每个方法都返回一个对象,该对象具有下一个方法作为属性。这意味着您可以使用类似reduce()之类的方法来继续调用从前一个对象返回的对象的下一个方法。

reduce()接受一个初始对象,您可以传递该初始对象以使事物滚动。像这样:

var tables = ["table1","table2","table3"]
let res = tables.reduce((res, table) => res.innerJoin(table), db.select(fields).from(table))

要了解其工作原理,我们可以创建一个伪db对象,其中包含所有方法,该方法返回该对象以用于链中的下一个方法。 innerJoin方法只是将参数添加到value属性:

// fake db object with these methods
const db = {
  select(t) {
    this.val = [] // initialize val
    return this
  },
  from(t) {
    return this
  },
  innerJoin(name) {
    this.val.push("Added: " + name)
    return this
  }
}

var tables = ["table1","table2","table3"]
// call innerjoin for each of the tables
// this is the same as chaining them
let res = tables.reduce((res, table) => res.innerJoin(table), db.select().from())

// values where accumlated in the val property
console.log(res.val)

答案 1 :(得分:-1)

我认为研究函数式编程将在这里为您提供帮助。

我在下面的Internet链接中使用了管道功能,但是您可以使用lodash / Ramda / underscore或任何您喜欢的实用程序库。

我在这里使用的两个主要概念是currying和管道。

  

What is 'Currying'?咖喱化是指将一个包含多个参数的函数分解为一系列包含一部分参数的函数   我们还利用了curring,该curring从另一个函数返回一个函数来编写新函数。

     

https://medium.com/@venomnert/pipe-function-in-javascript-8a22097a538e管道函数接受n个操作序列;每个操作都带有一个参数;处理它;并将处理后的输出作为该序列中下一个操作的输入。管道函数的结果是一个函数,它是操作序列的捆绑版本。

我们在这里要做的是获取一个数组,创建一个新的函数数组,我们希望将其应用于一个值。

所以我们要在数据库上进行大量的联接。

join => con => con.innerJoin(join);

接受一个值,即“ table1”,并返回一个带有数据库连接的函数,该函数调用联接并为下一个联接返回。

const joins = toJoin.map(join => con => con.innerJoin(join)); 这创建了要传递给管道的函数数组。

const db = ({
  select: function (field) {
    console.log('select', field)
    return db
  },
  from: function (table) {
    console.log('from', table)
    return db;
  },
  innerJoin: function (join) {
    console.log('innerJoin', join)
    return db;
  }
});

const _pipe = (a, b) => (arg) => b(a(arg));
const pipe = (args) => [].slice.apply(args).reduce(_pipe);

function joinInnerMultiple(table, fields, toJoin) {
  const joins = toJoin.map(join => con => con.innerJoin(join));

  return pipe(joins)(db.select(fields).from(table)); 
}


joinInnerMultiple("User", "uuid", ["table1", "table2", "table3", "table4", "table5"])