1.1.3 • Published 8 years ago

wrkflw v1.1.3

Weekly downloads
4
License
MIT
Repository
github
Last release
8 years ago

Workflow

Software License Travis Release npm Bower

A new type of deferred library for the browser.

Description

Workflow is the most simple deferred library for the browser JavaScript.

This will solve the problem in a different way than before.

Browser Support

  • Chrome: Current
  • Edge: Current
  • Firefox: Current
  • Internet Explorer: 9+
  • Safari: Current
  • Opera: Current

Installation

Download the latest release.

Clone the repo:

$ git clone https://github.com/node-link/workflow.git

Install with npm:

$ npm install wrkflw

Install with Bower:

$ bower install workflow

And, include as follows:

<script src="workflow.min.js"></script>

Demo

Workflow instance is "Array-like" Object.

var wf = new Workflow;

wf.push(function (next) {
  console.log('It can be pushed only function');
});

console.log(wf[0]);

Adding the function to operate as one of the processing block.

By executing the callback function called next(), to shift to the next processing.

wf.push(function (next) {
  console.log('process 1');
  next();
});

By calling the start(), to run the processing blocks that you defined.

wf.start();

Synchronous processing

As follows, you can run synchronously processing.

var wf = new Workflow;

// Process1
wf.push(function (next) {
  console.log('process1 start');
  setTimeout(function () {
    console.log('process1 is finished');
    next();
  }, 1000);
});

// Process2
wf.push(function (next) {
  console.log('process2 start');
  setTimeout(function () {
    console.log('process2 is finished');
    next();
  }, 1000);
});

// Start Workflow
wf.start(function (start) {

  // Start
  console.log('start');
  start();

}, function (again) {

  // End
  console.log('all of the processing is finished');

});

The above code will run the flow, such as:

Flowchart

Parallel processing

As follows, you can be the processing in parallel.

var wf = new Workflow;

// Process1
wf.push(
  Workflow.parallel(
    function (next) {
      console.log('process1-1 start');
      setTimeout(function () {
        console.log('process1-1 is finished');
        next();
      }, 1000);
    },
    function (next) {
      console.log('process1-2 start');
      setTimeout(function () {
        console.log('process1-2 is finished');
        next();
      }, 1000);
    }
  )
);

// Process2
wf.push(
  Workflow.parallel(
    function (next) {
      console.log('process2-1 start');
      setTimeout(function () {
        console.log('process2-1 is finished');
        next();
      }, 1000);
    },
    function (next) {
      console.log('process2-2 start');
      setTimeout(function () {
        console.log('process2-2 is finished');
        next();
      }, 1000);
    },
    Workflow.series(
      function (next) {
        console.log('process2-3-1 start');
        setTimeout(function () {
          console.log('process2-3-1 is finished');
          next();
        }, 1000);
      },
      function (next) {
        console.log('process2-3-2 start');
        setTimeout(function () {
          console.log('process2-3-2 is finished');
          next();
        }, 1000);
      }
    )
  )
);

// Start Workflow
wf.start(function (start) {

  // Start
  console.log('start');
  start();

}, function (again) {

  // End
  console.log('all of the processing is finished');

});

The above code will run the flow, such as:

Flowchart

State definition

To define the state will use the set() method. And to get the state will use the get() method.

var wf = new Workflow;

wf.push(function (next) {
  this.set('count', 0);
  next();
});

wf.push(function (next) {
  var count = this.get('count');
  this.set('count', count + 1);
  console.log(this.get('count'));  // 1
  next();
});

wf.push(function (next) {
  setTimeout(this.f(function () {
    var count = this.get('count');
    this.set('count', count + 1);
    console.log(this.get('count'));  // 2
    next();
  }), 1000);
});

wf.start();

console.log(wf.get('count'));

Callback function, such as those used in such as setTimeout is, by generating through f() method, to hold the this object.

If you specify an instance, it is also possible to get from the outside. In the example above, you can see if you call with wf.get('count').

The argument of set() and get() method, when you refer to an object, you can also use the dot notation.

wf.set('user', {id: 1, name: 'example'});
console.log(wf.get('user.name'));  // example

To delete a state, use the unset() method.

Watching state

By using the watch() method, you can monitor the state. And you can run the process each time it is changed.

var wf = new Workflow;

wf.push(function (next) {
  this.set('count', 0);
  next();
});

wf.push(function (next) {
  var count = this.get('count');
  this.set('count', count + 1);
  next();
});

wf.push(function (next) {
  setTimeout(this.f(function () {
    var count = this.get('count');
    this.set('count', count + 1);
    next();
  }), 1000);
});

wf.watch('count', function () {
  var counterElement = document.getElementById('counter');
  counterElement.innerHTML = this.get('count');
});

// You can also use the Workflow.series method, the Workflow.parallel method and the wf.join method
wf.watch('count',
  Workflow.series(
    function (next) {
      console.log('process1 start');
      setTimeout(function () {
        console.log('process1 is finished');
        next();
      }, 1000);
    },
    function (next) {
      console.log('process2 start');
      setTimeout(function () {
        console.log('process2 is finished');
        next();
      }, 1000);
    }
  )
);

wf.start();

watch() method, you can use a wildcard as follows:

wf.watch('users.*.age', function () {
  var counterElement = document.getElementById('user-' + this.get('users.*.id') + '-age');
  counterElement.innerHTML = this.get('users.*.age');
});

The contents of the asterisk can be referenced using the this.$.

wf.watch('posts.*.tags.*.name', function () {
  console.log(this.$[0]);
  console.log(this.$[1]);
});

wf.set('posts.2.tags.4.name', 'example');  // 2 4

By using the two asterisks, you can specify that you cross the dot.

wf.watch('posts.**.name', function () {
  console.log('!');
});

wf.set('posts.name', 'example');  // !
wf.set('posts.2.name', 'example');  // !
wf.set('posts.2.category.name', 'example');  // !
wf.set('posts.2.tags.4.name', 'example');  // !

To removes a watchpoint set with the watch() method, use the unwatch() method.

wf.watch('my.name', function () {
  console.log('!');
});

wf.set('my.name', 'example');  // !

wf.unwatch('my.name');

wf.set('my.name', 'example2');

Back to the previous processing block

The second argument of the function of Workflow is a function to return to the previous processing block.

var wf = new Workflow;

wf.push(function (next, prev, current) {
  this.set('count', 0);
  next();
});

wf.push(function (next, prev, current) {
  var count = this.get('count');
  this.set('count', count + 1);
  next();
});

wf.push(function (next, prev, current) {
  var count = this.get('count');
  console.log(count);
  if (count > 3) {
    next();
  } else {
    prev();
  }
});

wf.start();  // 1 2 3 4

And the third argument is the current function.

Process again

In the callback function of the start() method, you can execute the processing again.

var wf = new Workflow;

wf.push(function (next, prev, current) {
  var count = this.get('count');
  this.set('count', count + 1);
  next();
});

wf.push(function (next, prev, current) {
  var count = this.get('count');
  console.log(count);
  next();
});

wf.start(function (start) {
  this.set('count', 0);
  start();
}, function (again) {
  var count = this.get('count');
  if (count < 10) {
    again();
  }
});  // 1 2 3 4 5 6 7 8 9 10

Copy the processing to another instance

By using the join() method, it will be the processing block of an instance can be directly pushed to another instance.

var wf1 = new Workflow;

wf1.push(function (next) {
  console.log('one');
  next();
});

wf1.push(function (next) {
  console.log('two');
  next();
});

wf1.push(function (next) {
  console.log('three');
  next();
});

var wf2 = new Workflow;

wf2.push(wf1.join());

wf2.push(function (next) {
  console.log('four');
  next();
});

wf2.push(function (next) {
  console.log('five');
  next();
});

wf2.start();  // one two three four five

wf1.start();  // one two three

Example

In fact, it would be desirable to use in the following manner.

var wf = new Workflow;

wf.push(getMyJSON);
wf.push(checkMyUserExists);

wf.push(
  Workflow.parallel(
    getUserAndGroupJSON(1),
    getUserAndGroupJSON(2),
    getUserAndGroupJSON(3),
    getUserAndGroupJSON(4),
    getUserAndGroupJSON(5)
  )
);

wf.watch('users.*.group.name', function () {
  // rendering
  var elm = document.getElementById('group-name-' + this.get('users.*.groupId'));
  elm.innerHTML = this.get('users.*.group.name');
});

wf.start();

function getMyJSON(next) {
  // use jQuery
  jQuery.getJSON('my.json', this.f(function (json) {
    this.set('my', json.my);
    next();
  }));
}

function checkMyUserExists(next) {
  if (this.get('my.id')) {
    next();
  }
}

function getUserJSON(userId) {  // If you want to use the argument, let's use a closure
  return function (next) {
    jQuery.getJSON('users/' + userId + '.json', this.f(function (json) {
      this.set('users.' + userId, json.user);
      next();
    }));
  };
}

function getGroupJSON(userId) {
  return function (next) {
    // require group.id
    jQuery.getJSON('groups.json?' + jQuery.param({groupId: this.get('users.' + userId + '.groupId')}),
      this.f(function (json) {
        this.set('users.' + userId + '.group', json.group);
        next();
      }));
  }
}

function getUserAndGroupJSON(userId) {
  return Workflow.series(getUserJSON(userId), getGroupJSON(userId));
}

Since this is the only Deferred library, Rendering and XHR, etc. should be left to the other libraries.

Author

n0f

Follow

Licence

MIT

1.1.3

8 years ago

1.1.2

8 years ago

1.1.1

8 years ago

1.1.0

8 years ago

1.0.2

8 years ago

1.0.1

8 years ago

1.0.0

8 years ago

0.0.1

8 years ago