Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Playing around with tapable [questions] #71

Closed
nclsndr opened this issue Aug 27, 2018 · 4 comments
Closed

Playing around with tapable [questions] #71

nclsndr opened this issue Aug 27, 2018 · 4 comments

Comments

@nclsndr
Copy link

nclsndr commented Aug 27, 2018

Hello there,

I'm playing around with tapable outside of the Webpack world.

Basically, I'd like to use the async super-powers of tapable to expose hooks from a class method.

const { AsyncSeriesHook } = require('tapable')
const { ObjectId } = require('mongodb')
const capitalize = require('lodash/capitalize')
const { get, close } = require('./db')

// Root class
class Document {
  constructor(collection) {
    this.collection = collection
    this.data = {}
    this.hooks = {
      beforeCreate: new AsyncSeriesHook(['data', 'output']),
      afterCreate: new AsyncSeriesHook(['doc', 'output'])
    }
  }
  registerHook(hook, signature, promise) {
    const hookNames = Object.keys(this.hooks)
    if (!hookNames.includes(hook)) throw new Error(`Document do not contains "${hook}" hook`)
    this.hooks[hook].tapPromise(signature, promise)
  }
  async create(data) {
    const db = await get()
    const preHooksResult = new DataMap(data)
    await this.hooks.beforeCreate.promise(data, preHooksResult)
    const doc = await db
      .collection(this.collection)
      .insertOne(preHooksResult.get())
      .then(op => op.ops[0])
    const postHooksResult = new DataMap(doc)
    await this.hooks.afterCreate.promise(doc, postHooksResult)
    return postHooksResult.get()
  }
// ...
}

// instance creation
const user = new Document('users')
user.registerHook('beforeCreate', 'userType', async (data, output) => {
  output.merge({ type: 'user' })
})
user.registerHook('beforeCreate', 'validator', async (data, output) => {
  output.merge({ valid: true })
})
user.registerHook('afterCreate', 'idConverter', async (data, output) => {
  output.merge({ _id: data._id.toString() })
})

// call create
const res = await User.create({ firstName: 'Nico', lastName: 'D' })
console.log('res', res)

Here everything is working perfectly, so questions:

  1. Is tapable can/should be used for this type of implementation?
  2. Whatever I tried it's not possible to remove a hook previously set up, I imagine there is a rationale behind this, can you guys tell me about it?
  3. What is the role of the name in this.hooks[hook].tapPromise(name, promise)?

Thank you a lot

PS: You've done an amazing job with the design of this lib 😍

@ooflorent
Copy link
Member

ooflorent commented Sep 7, 2018

I imagine there is a rationale behind this, can you guys tell me about it?

The goal of tapable is to compile the callbacks to make their execution monomorphic (and fast). This is why all callbacks must be added before firing the event and cannot be removed (so there is no other compilation).

What is the role of the name … ?

Being able to identify who added the callback.

Is tapable can/should be used for this type of implementation?

Well, it could be but it is not optimal. Tapable is designed to create static hooks. Maybe async iterators would be a better fit for your system.

@nclsndr
Copy link
Author

nclsndr commented Sep 10, 2018

Thx you @ooflorent for your answer.
For sure using Tapable for this case wasn't the best idea, it made me learn at least 👍

to compile the callbacks to make their execution monomorphic

I'm curious about this, does anyone know where this is implemented in this repo?

Maybe async iterators would b a better fit for your system.

That's exactly the solution I end with. I rebuilt a very simple cascading async stack to reproduce the expected behavior.

@ooflorent
Copy link
Member

does anyone know where this is implemented in this repo?

https://github.com/webpack/tapable/blob/master/lib/HookCodeFactory.js

@nclsndr
Copy link
Author

nclsndr commented Sep 19, 2018

Thank you @ooflorent!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants