Я не уверен, что это именно то, что вы ищете, но я был бы склонен инвертировать поток управления, чтобы convert()
использовал или передавал «диспетчер ресурсов», который заботится о о создании, оснащении и удалении ресурса. A ResourceManager
может быть просто функцией, например:
type ResourceManager<T, I> = <R>(initProps: I, cb: (resource: T) => R) => R;
Итак, ResourceManager<T, I>
- это функция, которая принимает некоторый начальный пакет свойств типа I
, чтобы указать, какой ресурс типа T
необходим. и функция обратного вызова, которая выполняет фактическую работу после того, как ресурс станет доступным, но до его уничтожения. Если функция обратного вызова возвращает результат, то это делает и менеджер ресурсов.
Этот ResourceManager<T, I>
является общим контрактом c, который можно повторно использовать для различных типов ресурсов. Конечно, разные типы ресурсов нуждаются в собственных реализациях. Например, я бы вытащил из вашей convert()
функции a 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
.
Надеюсь, это поможет или даст вам несколько идей. Удачи!
Детская площадка ссылка на код