Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up

Middleware utility for your Promises

License

NotificationsYou must be signed in to change notification settings

sebelga/promised-hooks

Repository files navigation

NPM VersionBuild Statuscoveralls-imageCommitizen friendly

Addpre andpost middleware hooks to any function returning a Promise.
Readthe post on Medium for some example.

Install

yarn add promised-hooks# ornpm install promised-hooks --save`

Warp your Class/function/object

In order to add "pre" and "post" hooks to your promise you need to wrap their containing object (Class/function/object)

consthooks=require('promised-hooks');// ClassclassUser{// some method that returns a PromisesomeMethod(){ ...}}// FunctionfunctionUser(){}User.prototype.someMethod=functionsomeMethod(){ ...}// Objectconstapi={save:function(){ ...}};// Wrap them to add "pre" and "post" hooks functionalities to their methodshooks.wrap(User);hooks.wrap(api);

Add middleware

pre() method

Adds a middelware to a promise that will be resolved or rejectedbefore the method you are targetting. If the middelware rejects the Promise the original method isnot executed.All the parameters sent to the original methods are available in the arguments of your middleware.

consthooks=require('promised-hooks');classUser{// instance methodssave(){ ...}// works also with static methodsstaticotherMethod(){ ...}}hooks.wrap(User);User.pre('save',doSometingBeforeSaving);functiondoSometingBeforeSaving(){// Access the arguments passed if neededconstargs=Array.prototype.slice.apply(arguments);// the scope (this) is the original Object wrapped// return a PromisereturnnewPromise((resolve,reject)=>{// ... do some async stuff// then resolve or rejectresolve();});}

Override

You can override the original arguments sent to the target method by resolving the middleware with an object containing an "__override" property.

User.pre('save',doSometingBeforeSaving);functiondoSometingBeforeSaving(){returnnewPromise((resolve,reject)=>{// ...resolve({__override:123});// single argument// orresolve({__override:[123,'arg2']});// multi arguments});/**     * With the above override, the User.save() method will     * receive those arguments instead of the one originally provided     */}

post() method

Adds a middelware to be executedafter the method you are targetting has beenresolved. If the post middleware fails and rejects the Promise, the original Promise still resolves and the "post" errors are added the response (see below).

If you resolve your post middelware with an object containing an "__override" property (same as with "pre" hook), itwill override the original response.

consthooks=require('promised-hooks');classUser{// instance methodssave(){ ...}// works also with static (prototype) methodsstaticotherMethod(){ ...}}hooks.wrap(User);// Several middleware can be added at once with an ArrayUser.post('save',[postMiddleware1,postMiddleware2]);functionpostMiddleware1(data){// data is the resolved value from the original promised method// or previous "post" hooks with an __override property// do some async stuff ...// and resolve a PromisereturnPromise.resolve();// If needed, you can override the responsereturnPromise.resolve({__override:'my new response'});}functionpostMiddleware2(data){returnnewPromise((resolve,reject)=>{// call async service...myApi.doSomething((err)=>{if(err){/* if the async fails you would then reject your promise.                 * The original response is *not* overriden                 * (see errors in "post" hook below)                 */returnreject(err);}// no errorreturnresolve();});});}

Errors in "post" hooks

If one of the "post" hook fails and rejects its Promise then aSymbol is added on the response containing an Array with the errors.If the response is a primitive('string', 'number', boolean) then it is firstconverted to an object with a "result" property.

// For example, if the response returned by the targeted method is:'my response'// in case there are "post" hooks error it will be converted to:{result:'my response'}

You access the errors Array with thehooks.ERRORS Symbol.

consthooks=require('promised-hooks');classUser{save(){ ...}}hooks.wrap(User);User.post('save',postMiddleware);functionpostMiddleware(){returnnewPromise((resolve,reject)=>{// call async service...myApi.doSomething((err)=>{if(err){returnreject(err);}returnresolve();});});}// Somewhere else in your codeconstuser=newUser();user.save().then((response)=>{// The save occurred without issue but// let's check for any "post" hook errorif(response[hooks.ERRORS]){// deal with errors}...});

Scope (this)

The scope (this) of the middelware is set by default on the "wrapped" object. If you need to change it at runtime, you can declare a__scopeHook functionon the object that will be called for each hook. This method, when called, receives 3 parameters:

  • the target method
  • the arguments (array of arguments sent to the targeted method)
  • the hook method name
classUser{save(){}__scopeHook(targetMethod,args,hookMethod){console.log(targetMethod);// "save"console.log(args);// [123]console.log(hookMethod);// "hashPassword"// You can here return any object for the scopeif(hookMethod==='hashPassword'){return{x:'abc'};// set the scope}// If you return "undefined" the scope is not changedreturnundefined;}}hooks.wrap(User);User.pre('save',functionhashPassword(){// Check the scopeconsole.log(this);// { x: 'abc' }});// ...constuser=newUser();user.save(123).then( ...);

Example

consthooks=require('promised-hooks');classUser{save(userData){returnnewPromise((resolve,reject){// ...your logic to save a user thenresolve(response);});}// works also on static methodsstaticotherMethod(){ ...}}// Wrap the class to add hooks functionalitieshooks.wrap(User);// Hash a user password before savingUser.pre('save',(userData)=>{/**     * INFO: If you need to access the User class from this middelware     * you can not use an arrow function as the scope is lost.     * Use a normal function and *this* will be your Class    */if(typeofuserData.password!=='undefined'){userData.password=hashString(userData.password);}returnPromise.resolve();// ----------functionhashString(str){// ... logic to hash a stringreturnhashedString;}});// Let's email our newly created userUser.post('save',(response)=>{// response is what the target method returnsconstemail=response.email;// Return a method that returns a PromisereturnyourMailService.sendEmail(email);});// Create new userconstuser=newUser();// Save useruser.save({name:'John',password:'snow'}).then((response)=>{// Save success// Check if there are any errors in our "post" middlewareif(response.[hooks.ERRORS]){// deal with Post hook error}},(err)=>{// Save failed});

Credits

I have been inspired by thehooks-fixed library from @vkarpov15 to write this small utility.


[8]ページ先頭

©2009-2025 Movatter.jp