• Stars
    star
    108
  • Rank 321,259 (Top 7 %)
  • Language
    JavaScript
  • License
    MIT License
  • Created almost 10 years ago
  • Updated over 7 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

PromisePipe - reusable cross process promise chains

Build Status

#PromisePipe - reusable promise chains

Join the chat at https://gitter.im/edjafarov/PromisePipe

PromisePipe allows to build a reusable Promise chains. It returns a function which you can call multiple times and each time all chains will be called. The Function returns a promise each time you call it.

var pipe = PromisePipe()
			.then(doSmth)
            .then(doSmthElse);

var result = pipe(1); // calls doSmth, doSmthElse and returns a promise
// result is a Promise

PromisePipe is built with small core API. It can be extended with custom methods. You can build your domain specific API that describes your business logic.

var saveEventItem = PromisePipe()
  .validateItem(validationScheme)
  .saveItem()
  .updateItem()
  .catchError('item:add:reject')

PromisePipe is a singleton. You build chains of business logic and run the code both on server and client. Chains marked to be executed on the server will be executed on the server only and chains marked to be executed in the client will be executed in the client. You need to set methods in PromisePipe to pass messages from the client to the server. And it is up to you what transport to use.

promisepipeExample

check simple todo app

and todo with mongodb and session, live on heroku https://promisepipe-todo.herokuapp.com/

##install

npm install promise-pipe

Getting Started

The core API mimics api of Promise. So it should be pretty obvious how to use it. Additionally with data that is returned from previous chain as first argument each function have access to context object.

var PromisePipe = require('promise-pipe')(); //create a PromisePipe singleton

var someChain = function someChain(data, context){
  // do data transformations
  // change context
  return data; //pass data to next chain
}

var someAsyncChain = function someAsyncChain(data, context){
  return new Promise(function(resolve, reject){ //use Promise for async transformations
    // do data transformations
	// change context
    resolve(data) || reject(err)
  });
}

var handleError = function handleError(err, context){
  //handle error
  //change context
  return err;
}

var newPipe = PromisePipe()
  .then(someChain)
  .then(someAsyncChain)
  .catch(handleError);

var context = {};
var data = 1;

newPipe(data, context).then(function(result){
  //result is a result of the chain
});

#Core API

##PromisePipe() : pipe

###pipe : Promise Is a constructed pipe that returns a promise. First argument is a data, second is a context. While data behaves the same way as in Promises context is passing thorough whole chain of promises.

var pipe = PromisePipe()
.then(function(data, context){
  console.log(data, context);
    context.foo = "bar";
  return data + 1;
}).then(function(data, context){
  console.log(data, context);
    context.xyz = "baz";
  return data + 1;
}).then(function(data, context){
  console.log(data, context);
})
pipe(2, {});
//2 {}
//3 {foo:"bar"}
//4 {foo:"bar", xyz:"baz"}

###pipe.then .then adds a simple chain to the pipe

var pipe = PromisePipe()
.then(function(data, context){
  return //Promise.resolve/reject
})
.then(success)
.catch(fail)

###pipe.all As in Promises you can compose promise pipes

var pipe = PromisePipe()
.then(fn1)
.then(fn2)
.all(
  PromisePipe()
  .then(fnasync11)
  .then(fnasync21)
  .then(fnasync31)

  ,PromisePipe()
  .then(fnasync12)
  .then(fnasync22)
  .then(fnasync32)
)
.then(fnEnd)

###pipe.catch The catch is catching error or reject of previous chains. Behaves as Promise catch.

###pipe.join You can join PromisePipes if you like.

var pipe = PromisePipe()
.then(function(data, context){
  return data + 1;
});

var pipe2 = PromisePipe()
.then(function(data, context){
  return data + 2;
})
.join(pipe)
.then(function(data){
  console.log(data);
});

pipe2(1) //4

##PromisePipe.use(name, handler) Allows to build your own customized DSL. handler is a function with at least 2 arguments data and context as in simple chain.

function handler(data, context, arg1, ..., argN){
  //you can return Promise
  return data;
}
PromisePipe.use('custom', handler);

PromisePipe().custom(arg1, ..., argN)

Other arguments arg1, ..., argN are used to additionally modify the chain behavior. For example we can build smarter log() method:

var PromisePipe = require('promise-pipe')();

PromisePipe.use('log', function(data, context, name){
  if(name) {
    console.log(data[name]);
  } else {
    console.log(data)
  }
  return data;
})

var action = PromisePipe()
			  .log()
              .log('foo');

action({foo:"baz", bar:"xyz"})
// {foo:"baz", bar:"xyz"} <- log()
// baz <- log('foo')

##Transitions When the PromisePipe is running on several environments and the execution comes to a chain marked to be executed on other environment PromisePipe tries to pass a message to that environment. To make it work you should describe how to pass the message between environments. Following methods are built for that.

###PromisePipe.setEnv With .setEnv method you are setting environment for the PromisePipe. All methods marked same as the pipe will be executed only in this environment.

if(typeof(window) !== 'object'){
  PromisePipe.setEnv('server');
} else {
  PromisePipe.setEnv('client');
}

###PromisePipe.in Creates wrapper that marks chains as executable in specific environment.

var doOnServer = PromisePipe.in('server')
var addItemAction = PromisePipe()
  .then(validateItem)
  .then(doOnServer(validateItemServer)) // will be executed on server
  .then(doOnServer(saveItemInDB)) // will be executed on server
  .then(addItem)
  .catch(handleError);
addItemAction(item) // will pass complete chain

###PromisePipe.envTransition(from, to, handler) Setting transition of a message between environments. from and to are environments names. For example 'client' and 'server'. handler is a function that passes the message to other env.

PromisePipe.envTransition('client', 'server', function(message){
  // here you need to put a logic that sends message to server env
})

###PromisePipe.execTransitionMessage(message) The message created in PromisePipe.envTransition comes to another env and must be executed here. When the message is prepared you need to execute it on a PromisePipe. It will resolve what chains it need to execute and will return a Promise that you need to handle and return updated message back to client.

function serverHandler(message){
  PromisePipe.execTransitionMessage(message).then(function(data){
	message.data = data;
    //sendToClient(message);
  });
}

On client you would also need to execute the message that comes back:

function clientHandler(message){
  PromisePipe.execTransitionMessage(message);
}

###PromisePipe.localContext(context) : PromisePipeWithContext With serverside you would probably need to have some isolated context like session that should not be accessible on client. You can extend the context for environment. (Usage Eaxmple)

PromisePipeWithContext.execTransitionMessage(message)

The message will be executed with access to additional context.

PromisePipeWithContext.wrap(fn)

The function will be executed with access to additional context.

##Connectors To make connecting different environments easier there is connectors API.

###PromisePipe.stream(from, to, Handler).connector(Connector) This is setting up transitions to use Connector.

Connector is an object that should implement two methods: send and listen

{
  send: function(message){
    //send message
  },
  listen: function(handler){
    //if message comes call handler function with the message object
  }
}

There are implemented connectors for SocketIO, HTTP, SocketIO + sessions, Webworkers

##Debugging ###PromisePipe.setMode To set up PromisePipe in debug mode you need to call PromisePipe.setMode('DEBUG'). Then in chrome you will be able to see in console values of arguments passed inside each chain within pipe:

debuggability promisepipes

More Repositories

1

remote-impress

This is remote Impress.js and Deck.js presentation controller. Allows to use phone for switching slides.
JavaScript
88
star
2

node-webkit-desktop-notification

node-webkit-desktop-notification
JavaScript
52
star
3

socker

CRUD over engine.io websockets
JavaScript
45
star
4

grail

grail - isomorphic app framework
JavaScript
25
star
5

compy

lightweight html app builder
JavaScript
19
star
6

getapi

allows to build API's using annotations
JavaScript
11
star
7

aries

AriesNode is a MVC framework for node.
JavaScript
10
star
8

nodejs-api-boilerplate

nodejs-api-boilerplate project for workshop
JavaScript
5
star
9

nodejswall

Twitter wall written totally in Node.js
JavaScript
4
star
10

workersQueue

tasks queue for multiple workers
JavaScript
3
star
11

gql-json-slicer

JavaScript
3
star
12

edjafarov.github.io

CSS
3
star
13

fluxnot

JavaScript
3
star
14

pdfer

simple out of the box pdf-service, heroku deployable
JavaScript
2
star
15

reactjs-boilerplate

odessajs reactjs-boilerplate
JavaScript
2
star
16

metamodule

Analyses files for exports statically. Reads comments, assigned functions with arguments
JavaScript
1
star
17

jsgroup-node-presentation

presentation of node.js 18.02.12
JavaScript
1
star
18

component-jsx

component plugin for JSXtransformation
JavaScript
1
star
19

secure.me

security helper for express. You can make all endpoints secure at once and control accessibility of each endpoint.
JavaScript
1
star
20

component-typescript

JavaScript
1
star
21

http-connector

PromisePipe Http connector
JavaScript
1
star
22

classloader

nodejs class loader
JavaScript
1
star
23

rdist

JavaScript
1
star
24

squeezer

array to object transformator
JavaScript
1
star