Javascript 如何构建方法链运行和查找周期(冲突)

Javascript 如何构建方法链运行和查找周期(冲突),javascript,recursion,graph-theory,Javascript,Recursion,Graph Theory,我所拥有的:有一些json配置(描述性模板),方法以不同的顺序存储,其外观如下: [ { “名称”:“methodA”,//methodA输出参数是methodB输入参数 “inArgs”:“[arg1,arg2]”, “返回args:”[arg3,arg4]“ }, { “名称”:“methodB”,//methodB输出参数是methodZ输入参数 “inArgs”:“[arg3,arg5]”, “返回args:”[arg6,arg7]“ }, { “名称”:“方法С”, “inArgs”:

我所拥有的:有一些json配置(描述性模板),方法以不同的顺序存储,其外观如下:

[
{
“名称”:“methodA”,//methodA输出参数是methodB输入参数
“inArgs”:“[arg1,arg2]”,
“返回args:”[arg3,arg4]“
},
{
“名称”:“methodB”,//methodB输出参数是methodZ输入参数
“inArgs”:“[arg3,arg5]”,
“返回args:”[arg6,arg7]“
},
{
“名称”:“方法С”,
“inArgs”:“[arg1]”,
“返回args”:“[arg10]”
},
一组其他方法,其输入参数不是methodA或methodB的一部分
.....
{
“名称”:“methodZ”,
“inArgs”:“[arg6,arg11]”,
“返回args”:“[arg20]”
}
]
我需要将这些方法按正确的顺序(链)运行,如:


methodC//此方法的输出不用作其他方法的输入参数
方法A//我需要正确的顺序
方法B
methodZ
第二种情况

[
.....
{
“name”:“methodX”,//methodX输出参数是methodY输入参数
“inArgs”:“arg1、arg2、arg3],
“返回args”:«[arg4、arg5、arg6]»
},
{
“name”:“methodY”,//methodY输出参数是methodX输入参数
“inArgs”:«[arg4,arg5,arg7]»,
“返回args”:«[arg8、arg9、arg10]»
},
....
{
“name”:“methodZ”,//methodZ输出参数是methodX输入参数(冲突或循环,所以抛出错误)
“inArgs”:«[arg8,arg11,arg12]»,
“返回args”:«[arg3,arg13,arg14]»
},
]
由于一个方法的输出参数可以是另一个方法的输入参数(也可以通过一系列不确定嵌套的方法),因此有必要捕获此类冲突,最好是在解析配置的阶段

有人能为这样一个问题提供最佳解决方案吗?到目前为止,我只想到图表


对不起,我说的是英语。

一个更简单但不是防弹的(你无法检测周期)解决方案是将每个值包装成一个承诺:当函数生成某些输出时,解析承诺,然后使用
Promise。所有输入都
。这样,承诺将自动确定正确的顺序:

const context = { /* [var: string]: { resolve(v: T), value: Promise<T> */ };

function getVar(name) {
 if(context[name]) return context[name].value;
 const cont = context[name] = { };
 return cont.value = new Promise(res => cont.resolve = res);
}

function setVar(name, value) {
 getVar(name); // Make sure prop is initialized, don't await!
 context[name].resolve(value);
}

async function run(fn, argNames, resultNames) {
   const args = await Promise.all(argNames.map(getVar));
   const results = fn(...args);
   for(let i = 0; i < results.length; i++)
     setVar(resultNames[i], results[i]);
}
const context={/*[var:string]:{resolve(v:T),value:Promise*/};
函数getVar(名称){
if(context[name])返回context[name].value;
const cont=上下文[名称]={};
return cont.value=新承诺(res=>cont.resolve=res);
}
函数setVar(名称、值){
getVar(name);//确保prop已初始化,不要等待!
上下文[名称]。解析(值);
}
异步函数运行(fn、argNames、resultNames){
const args=wait Promise.all(argNames.map(getVar));
const results=fn(…args);
for(设i=0;i
(对不起,这是一个很长的答案。我希望它有用。)

我喜欢的答案 我开始尝试使用您正在寻找的API来解决这个问题。我确实设法做到了一些合理的接近。但这不是我个人会使用的东西。我重写了API并多次重构了实现,直到我找到了我想要使用的东西。下面我将讨论我的早期步骤(这可能与您更相关)但以下是我将如何使用我的版本:

const def={
url:(服务器,路径,查询,片段)=>`${server}/${path | |''''}${query | |''}${fragment?`${fragment}:''}},
query:(parameters)=>parameters?'?'+Object.entries(parameters).map([k,v])=>`${k}=${v}`)。join('&'):'',
服务器:(架构,端口,主机)=>`${schema}:/\/${host}${port&&(字符串(端口)!='80')?`:${port}:''}`,
主机:(域,子域)=>`${subdomain?`${subdomain}.`:''}${domain}`,
}
常数={
架构:“https”,
端口:'80',
域:“example.com”,
子域:“测试”,
路径:'path/to/resource',
参数:{foo:42,bar:'abc'},
片段:“baz”,
}
运行函数(def)(VAL)
这将生成如下输出:

{
架构:“https”,
端口:“80”,
域名:“example.com”,
子域:“测试”,
路径:“路径/到/资源”,
参数:{foo:42,bar:“abc”},
片段:“baz”,
查询:“?foo=42&bar=abc”,
主持人:“test.example.com”,
服务器:“https://test.example.com",
url:“https://test.example.com/path/to/resource?foo=42&bar=abc#baz"
}
API设计 我在这个版本中看到的主要优点是API感觉非常干净。配置对象只是将名称映射到函数,提供给结果函数的数据对象只是将名称映射到这些函数所需的初始参数。结果是该数据对象的增强版本。初始调用返回一个reusa这个函数很简单

实施 我写这篇文章的一些历史记录已经嵌入到设计中。它可能需要很好的重构;一些辅助函数可能不是必需的。但目前它包括:

  • 四个简单的辅助函数:

    • isEmpty
      报告数组是否为空
    • removeIndex
      的作用类似于一个不可变的
      拼接
      ,返回一个数组的副本,而不返回其
      n
      th索引
    • props
      将属性名称数组映射到给定对象中的属性值
    • error
      只需将字符串包装在错误中并抛出它
  • 一个不那么重要的辅助函数:

    • parseArgs
      从函数中检索参数名。它基于。(奇怪的是,我尝试的第一个参数在测试REPL中运行良好,但在StackOverflow代码段中失败。)
  • 四个主要功能:

    • preprocess
      将描述对象转换为与问题中描述的结构类似的配置对象(使用
      name