函数使用对象来初始化和销毁 资源。如何将其重写为提供资源的HOF?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了函数使用对象来初始化和销毁 资源。如何将其重写为提供资源的HOF?相关的知识,希望对你有一定的参考价值。

这是我的开始。 convert使用svgInjector初始化和销毁​​资源。

export async function convert(
  serializedSvg: string,
  svgSourceId: string,
  containerId: string
): Promise<string> {
  const svgInjector = new SvgInjector(serializedSvg, containerId).inject();
  if (!svgInjector.injectedElement) {
    throw new Error("Svg not injected");
  }

  const doc = new TargetDocument({});
  const xml = convertRecursively(
    svgInjector.injectedElement,
    doc,
    {
      svgSourceId,
    }
  );

  svgInjector.remove();

  return doc.saveXML();
}

我该如何重写它,以代替具有更高阶的函数来启动,提供和销毁资源svgInjector.injectedElement到convert函数?

编辑:

这里是一个最小的可复制示例:

var svg = '<svg xmlns="http://www.w3.org/2000/svg"><text x="20" y="20">I am made available in DOM</text></svg>'

function convert(
  serializedSvg,
  containerId
) {
  // make resource available (cross-cutting convern)
  var container = document.getElementById(containerId);
  var resource = new DOMParser().parseFromString(serializedSvg, "image/svg+xml").documentElement;
  container.appendChild(resource);

  // core convert functionality does things with resource
  console.log(resource.getBBox())
  
  // clean up resource (cross-cutting concern)
  resource.remove()
}

convert(svg, "container")
<!DOCTYPE html>
<html>
<head>
  <title>Minimal</title>
</head>
<body>
<div id="container">
</div>
</body>
</html>

编辑2

这里是上一次编辑的javascript的TypeScript版本

var svg = '<svg xmlns="http://www.w3.org/2000/svg"><text x="20" y="20">I am made available in DOM</text></svg>'

function convert(
  serializedSvg: string,
  containerId: string
) {
  // make resource available (cross-cutting convern)
  var container = document.getElementById(containerId);
  if (!(container instanceof HTMLDivElement)) {
    throw new Error("Extpected a div element")
  }
  var resource = new DOMParser().parseFromString(serializedSvg, "image/svg+xml").documentElement;
  if (!(resource instanceof SVGSVGElement)) {
    throw new Error("Extpected a svg element")
  }
  container.appendChild(resource);

  // core convert functionality does things with resource
  console.log(resource.getBBox())

  // clean up resource (cross-cutting concern)
  resource.remove()
}

convert(svg, "container")
答案

我不确定这是否正是您要寻找的东西,但是我倾向于反转控制流,以便convert()使用或传递一个“资源管理器”来处理资源的创建,提供和删除。 ResourceManager可能只是一个函数,例如:

type ResourceManager<T, I> = <R>(initProps: I, cb: (resource: T) => R) => R;

因此ResourceManager<T, I>是一个函数,该函数使用一些I类型的初始属性包来指定需要哪个T类型的资源,并且是一个回调函数,该回调函数在资源可用之后且在其之前执行实际工作被摧毁。如果回调函数返回结果,那么资源管理器也将返回结果。

[ResourceManager<T, I>是可用于不同类型资源的通用合同。当然,不同类型的资源需要它们自己的实现。例如,我将从convert()函数中抽出一个ResourceManager<SVGSVGElement, { serializedSvg: string, containerId: string }>,如下所示:

const svgManager: ResourceManager<SVGSVGElement, { serializedSvg: string, containerId: string }> =
  (initProps, cb) => {

    // make resource available)
    var container = document.getElementById(initProps.containerId);
    if (!(container instanceof HTMLDivElement)) {
      throw new Error("Extpected a div element");
    }
    var resource = new DOMParser().parseFromString(initProps.serializedSvg, "image/svg+xml").documentElement;
    if (!(resource instanceof SVGSVGElement)) {
      throw new Error("Extpected a svg element")
    }
    container.appendChild(resource);

    // core functionality
    const ret = cb(resource);

    // clean up resource
    resource.remove()

    // return returned value if we have one
    return ret;
  }

请注意,“核心功能”只是如何推迟到回调,在需要时其返回值将保留。然后,convert()简化为:

function convert(
  serializedSvg: string,
  containerId: string
) {
  svgManager({ serializedSvg, containerId }, (resource => console.log(resource.getBBox())));
}

resource => console.log(resource.getBBox())是执行工作而不关心如何获取或处置resource的功能。


希望有帮助或为您提供一些想法。祝你好运!

Playground link to code

另一答案

到目前为止,这是我最好的尝试。我希望更聪明的人发布更好的解决方案。

下面看到的解决方案的两个弱点是:

  • 增强子的类型不是通用的,阻碍了重用
  • 增强剂需要结合,阻碍了增强剂的合成
    type Props = {
      svg: SVGSVGElement;
      svgSourceId: string;
      containerId: string;
    };

    async function convertBase(props: Props): Promise<string> {
      const doc = new TargetDocument({});
      const xml = convertRecursively(props.svg, doc, {
        svgSourceId: props.svgSourceId,
      });

      return doc.saveXML();
    }

    type EnhancerProps = {
      serializedSvg: string;
      svgSourceId: string;
      containerId: string;
    };

    type EnhancerPropsLight = {
      svgSourceId: string;
      containerId: string;
    };

    function enhancer(fn: Function, props: EnhancerProps) {
      const rest = omit(["serializedSvg"])(props) as EnhancerPropsLight;
      const svgInjector = new SvgInjector(
        props.serializedSvg,
        props.containerId
      ).inject();
      if (!svgInjector.injectedElement) {
        throw new Error("Svg not injected");
      }

      const res = convertToTgmlBase({ ...rest, svg: svgInjector.injectedElement });

      svgInjector.remove();

      return res;
    }

    const convert = enhancer.bind(null, convertBase);
    export { convert };

以上是关于函数使用对象来初始化和销毁 资源。如何将其重写为提供资源的HOF?的主要内容,如果未能解决你的问题,请参考以下文章

使用智能指针来管理对象 (基于RAII)

C++C++的拷贝控制

29.Python面向对象类:主要讲初始化方法__init__,垃圾回收,继承&多继承,方法重写,super()函数

29.Python面向对象类:主要讲初始化方法__init__,垃圾回收,继承&多继承,方法重写,super()函数

拷贝控制——拷贝赋值与销毁

29.Python面向对象类:主要讲初始化方法__init__,垃圾回收,继承&多继承,方法重写,super()函数