Coder Social home page Coder Social logo

definit's Introduction

Overview

Diff and deinit to definitely clean up resources. Compares two data structures and calls a destructor method on every inner object that's been "removed".

A small subset of Espo, extracted as a separate library.

Useful for automatic cleanup when you store stuff in "immutable" structures, creating new versions instead of mutating them. Works well with ES2018 object spread or Emerge.

Why

Automatic resource cleanup: store and remove objects without worrying about forgetting to call destructors.

Installation

npm i -E definit

Usage

deinitDiff(prev, next)

Diffs prev and next, deiniting any objects that implement isDeinitable (see below) and exist in prev but not in next. The diff algorithm recursively traverses plain data structures, but stops at non-plain objects, allowing you to safely include objects of arbitrary size and structure.

Definition of “plain data”:

  • primitive: number, string, boolean, symbol, null, undefined
  • {} or Object.create(null)
  • array

Everything else is considered non-data and is not traversed.

Resilient to exceptions: if a deiniter or a property accessor produces an exception, deinitDiff will still traverse the rest of the tree, delaying exceptions until the end.

Avoids cyclic references.

class Resource {
  constructor (name) {this.name = name}
  deinit () {console.info('deiniting:', this.name)}
}

class BlackBox {
  constructor (inner) {this.inner = inner}
}

const prev = {
  root: new Resource('Sirius'),
  dict: {
    inner: new Resource('Arcturus'),
  },
  list: [new Resource('Rigel')],
  // Sun is untouchable to deinitDiff because it's wrapped
  // into a non-plain object that doesn't implement isDeinitable
  blackBox: new BlackBox(new Resource('Sun'))
}

const next = {
  root: prev.root,
  dict: {
    inner: new Resource('Bellatrix')
  },
  list: null,
}

deinitDiff(prev, next)

// 'deiniting: Arcturus'
// 'deiniting: Rigel'

deinitDiff(next, null)

// 'deiniting: Sirius'
// 'deiniting: Bellatrix'

deinitDeep(value)

Same as deinitDiff(value, undefined). Deeply deinits the entire outgoing value.

const tree = {
  one: {deinit() {console.info('cleanup!')}},
  two: {deinit() {console.info('cleanup!')}},
}

deinitDeep(tree)

isDeinitable(value)

True if value has a .deinit method.

isDeinitable({deinit() {}})
// true

isDeinitable({})
// false

State Container

definit is useful for adding automatic resource cleanup to a state container: a popular pattern for storing immutable data on a mutable reference. Redux is a popular example, but you don't actually need a library for this.

This state container is copied from my production apps:

import {deinitDiff} from 'definit'

class Ptr {
  constructor(value) {
    this.$ = value
  }

  swap(fun) {
    const prev = arguments[0] = this.$
    deinitDiff(prev, this.$ = fun.apply(undefined, arguments))
  }

  reset(next) {
    deinitDiff(this.$, this.$ = next)
  }

  deinit() {
    deinitDiff(this.$, undefined)
  }
}

Usage:

const env = new Ptr({})

const xhr = new XMLHttpRequest()
const request = {xhr, deinit() {xhr.abort()}}

env.swap(state => ({...state, request}))

env.$
// {request: {xhr, deinit}}

// Removing the request also aborts it
env.swap(state => ({...state, request: undefined}))

env.$
// {request: undefined}

Misc

I'm receptive to suggestions. If this library almost satisfies you but needs changes, open an issue or chat me up. Contacts: https://mitranim.com/#contacts

definit's People

Contributors

mitranim avatar

Watchers

 avatar  avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.