Skip to content

Commit

Permalink
allowed additional arguments to be passed to class methods when used …
Browse files Browse the repository at this point in the history
…with next(), error(), twoPrev() and threePrev()

added am.extend() static method
  • Loading branch information
ingenious committed Jan 26, 2018
1 parent 30efae0 commit e4f8c14
Showing 10 changed files with 368 additions and 95 deletions.
151 changes: 106 additions & 45 deletions README.md
Original file line number Diff line number Diff line change
@@ -12,7 +12,7 @@
> * Extensible. easily add additional *Extended Promise* methods
## Changes in version 0.2.5
## Changes in version 0.2.15

[changes.MD](https://github.com/ingenious/async-methods/blob/master/changes.MD)

@@ -89,7 +89,7 @@ In package.json

```javascript

"async-methods":"^0.2.9"
"async-methods":"^0.2.15"

```

@@ -109,6 +109,12 @@ In code

```

## Node versions and support for async/await

**async/await** is only available from version 7.6 of node.js. If you are using an earlier version you will not be able to use the async/await features of **async-methods**. **async-methods** will still work for wrapping generators and classes with normal functions and generator functions in versions earlier than 7.6.

Generators have been supported in nmodejs since at lease version 4.8.7

## Handling Promise rejections

NodeJS requires all rejections in a Promise chain to be handled or an exception is thrown.
@@ -133,7 +139,7 @@ at the end of the chain (see examples below). That way errors will be trapped a

### Wrap ES6 Class with methods

#### am( methodName , class { methodName { ... }})
#### am( methodName , class { methodName { ... }}, args ...)

```javascript

@@ -178,7 +184,7 @@ let ep = am(

### Wrap Newed Class

#### am(methodName, new class(args...))
#### am(methodName, new class <name> {methodName (){}}(),args..)
```javascript

@@ -245,6 +251,45 @@ Create *ExtendedPromise* that returns an array.

})

```

### Wrap generator

#### am(generator)

Creates *ExtendedPromise* (in same way as to 'co')

```javascript

am(function* () {

return yield {

b: Promise.resolve('bb'),
a: {
b: Promise.resolve('bb'),
a: {
b: Promise.resolve('bb'),
c: Promise.resolve('cc')
}
}
};

})

.log()

// logs:
// yield object with async attributes { b: 'bb', a: { b: 'bb', a: { b: 'bb', c: 'cc' } } }​​​​​

.error(err=>{

// handle errors at end of chain

})



```

#### Wrapping non-object
@@ -359,45 +404,6 @@ Creates *ExtendedPromise* that returns arguments of the callback and passes any

})

```

### Wrap generator

#### am(generator)

Creates *ExtendedPromise* (in same way as to 'co')

```javascript

am(function* () {

return yield {

b: Promise.resolve('bb'),
a: {
b: Promise.resolve('bb'),
a: {
b: Promise.resolve('bb'),
c: Promise.resolve('cc')
}
}
};

})

.log()

// logs:
// yield object with async attributes { b: 'bb', a: { b: 'bb', a: { b: 'bb', c: 'cc' } } }​​​​​

.error(err=>{

// handle errors at end of chain

})



```

### Wrap Promises
@@ -1454,6 +1460,22 @@ Identical to **<Promise>.catch()** but returns a chainable *ExtendedPromise*.

If want **fn** to be a generator or class use **.error()**

#### Additional Arguments passed to class methods

When wrapping a class and specifying a method name, arguments to be passed to the method can be added can be added as arguments of the wrappimg am(). The same is true for anonymous and named classes used as arguments to

#### next(methodName,class,...), error(methodName,class,...),

Additional arguments added to **next(methodName,class,...)** are **prepended** to the resolved result of previous step and appled as arguments to the method. Thiis si useful if you don'tt want the result to be used by the method but wish to apply other arguments.

#### twoPrev(methodName,class,...), threePrev(methodName,class,...)

Additional arguments added to **twoPrev(methodName,class,...)** are **appended** to the resolved result of previous two steps and appled as arguments to the method. The main purpose of twoPrev is to pass two results to a method. If additional arguments are required they can be added in this way.

Additional arguments added to **threePrev(methodName,class,...)** are **appended** to the resolved result of previous three steps and appled as arguments to the method. The main purpose of threePrev is to pass three results to a method. If additional arguments are required they can be added in this way.

<hr/>

## Static methods

>All static methods return a chainable Extended Promise
@@ -1750,13 +1772,52 @@ These methods have same functionality as their Promise equivalents but return a

### async-methods Extensions

You can now roll-your-own Extended Promise, adding more methods or changing functionality of exiting methods!
Developerts can roll-their-own Extended Promise, adding more methods or changing functionality of exiting methods!
See ***am-sample-ext.js*** and check out this Mongo extension: [am-mongo](https://github.com/ingenious/am-mongo)

In application code, **async-methods (am)** can be extended progressively using **am.extend()** static mmthod. Some new standard extensions are due for release soon, but applicastion developers can create their own and reference them by a filepath as well as by an npm module name.

```javascript

let am = require('am-mongo')

am.extend(['../../am-axios.js', '../../am-cron.js'])

// as well as additional am.xxx() static methods
// am with now be extended with am-mongo, am-axios and am-cron methods available in the chain

```

This would have the same effect:

```javascript

let am = require('async-methods')

am.extend(['am-mongo',../../am-axios.js', '../../am-cron.js'])
// am with now be extended with am-mongo, am-axios and am-cron methods available in the chain
// as well as additional am.xxx() static methods
```
A single extension can be specified also
```javascript
let am = require('async-methods')
am.extend('am-mongo')
// am with now be extended with am-mongo, methods available in the chain
// as well as additional am.xxx() static methods
```
### am._extend(ExtendedPromise)
#### For use in creating an extension
#### For use internally in creating an extension
See **am-sample-ext.js** for more explanation
88 changes: 75 additions & 13 deletions am.js
Original file line number Diff line number Diff line change
@@ -54,9 +54,14 @@ class ExtendedPromise extends Promise {
})
.error(reject)
} else if (argsHaveClass) {
let newResult
let newResult,
args = [result]
if (argsHaveClass.args) {
// prepend any arguments added in method arguments to resolved value from previous step(s) in chain
args = argsHaveClass.args.concat([result])
}
try {
newResult = am.ExtendedPromise._applyResultToClass(argsHaveClass, [result])
newResult = am.ExtendedPromise._applyResultToClass(argsHaveClass, args)

// in case newResult is Promise
am(newResult)
@@ -110,7 +115,8 @@ class ExtendedPromise extends Promise {
argsHaveClass = am.argumentsHaveClass(arguments),
applyResultToClass = am.ExtendedPromise._applyResultToClass,
mapFilter = true,
newContext = {}
newContext = {},
args
for (var attr in self._state_) {
newContext[attr] = self._state_[attr]
}
@@ -121,7 +127,12 @@ class ExtendedPromise extends Promise {
reject(err)
} else if (argsHaveClass && !am.isArray(result) && !am.isObject(result)) {
//non-object/array applied to class (synchronous/asynchronous)
applyResultToClass(argsHaveClass, [result])
args = [result]
if (argsHaveClass.args) {
// prepend any arguments added in method arguments to resolved value from previous step(s) in chain
args = argsHaveClass.args.concat([result])
}
applyResultToClass(argsHaveClass, args)
.next(resolve)
.catch(reject)
} else if (!argsHaveClass && !am.isGenerator(fn) && am.isObject(result)) {
@@ -529,7 +540,8 @@ class ExtendedPromise extends Promise {
let self = this,
argsHaveClass = am.argumentsHaveClass(arguments),
applyResultToClass = am.ExtendedPromise._applyResultToClass,
newContext = {}
newContext = {},
args
for (var attr in self._state_) {
newContext[attr] = self._state_[attr]
}
@@ -557,7 +569,12 @@ class ExtendedPromise extends Promise {
})
.error(reject)
} else if (argsHaveClass) {
applyResultToClass(argsHaveClass, [err])
args = [err]
if (argsHaveClass.args) {
// prepend any arguments added in method arguments to resolved value from previous step(s) in chain
args = argsHaveClass.args.concat([err])
}
applyResultToClass(argsHaveClass, args)
.next(function(newResult) {
// pass through if nothing returned
if (newResult === undefined) {
@@ -606,18 +623,33 @@ class ExtendedPromise extends Promise {
// class with specified method (new first)
try {
newedClass = new argsHaveClass.classFn()
wrappedNewResult = am(newedClass[argsHaveClass.methodName].apply(self, args))
if (!newedClass[argsHaveClass.methodName]) {
wrappedNewResult = am.reject(
argsHaveClass.methodName + ' is not a methodName of the specified Class'
)
} else {
wrappedNewResult = am(newedClass[argsHaveClass.methodName].apply(self, args))
}
} catch (e) {
wrappedNewResult = am.reject(e)
}
} else if (argsHaveClass.classObject && argsHaveClass.methodName) {
// newed class with specified method
try {
wrappedNewResult = am(
argsHaveClass.classObject[argsHaveClass.methodName].apply(argsHaveClass.classObject, args)
if (!argsHaveClass.classObject[argsHaveClass.methodName]) {
wrappedNewResult = am.reject(
argsHaveClass.methodName + ' is not a methodName of the specified Class'
)
} catch (e) {
wrappedNewResult = am.reject(e)
} else {
try {
wrappedNewResult = am(
argsHaveClass.classObject[argsHaveClass.methodName].apply(
argsHaveClass.classObject,
args
)
)
} catch (e) {
wrappedNewResult = am.reject(e)
}
}
} else if (argsHaveClass.classFn) {
// .next(Class)
@@ -660,6 +692,11 @@ class ExtendedPromise extends Promise {
.next(function(args) {
if (argsHaveClass) {
let newResult

// append any additional arguments passed to threePrev*() to the last 3 results
if (argsHaveClass.args) {
args = args.concat(argsHaveClass.args)
}
try {
am.ExtendedPromise._applyResultToClass(argsHaveClass, args)
.next(function(newResult) {
@@ -735,6 +772,11 @@ class ExtendedPromise extends Promise {
.next(function(args) {
if (argsHaveClass) {
let newResult

// append any additional arguments passed to threePrev*() to the last 3 results
if (argsHaveClass.args) {
args = args.concat(argsHaveClass.args)
}
try {
am.ExtendedPromise._applyResultToClass(argsHaveClass, args)
.next(function(newResult) {
@@ -772,7 +814,6 @@ class ExtendedPromise extends Promise {
reject(e)
}
} else {
console.log(756)
am(args)
.next(resolve)
.error(reject)
@@ -1365,6 +1406,27 @@ am.sfFn = function(initial) {
)
}

// add one or more extensions to an existing instance
am.extend = function(extensionPackageList) {
if (!am.isArray(extensionPackageList)) {
extensionPackageList = [extensionPackageList]
}
extensionPackageList.forEach(function(extensionPackage) {
let amVersion = require(extensionPackage)
try {
for (var method in amVersion) {
if (!am[method]) {
am[method] = amVersion[method]
}
}

am._extend(amVersion.ExtendedPromise)
} catch (e) {
console.log(1397, 'Problem extending am with ', extensionPackage, e)
}
})
return am
}
am._extend = function(extendedPromise) {
// back extend async methods ExtendedPromise class
let superMethodNames = am.methodNames
Loading

0 comments on commit e4f8c14

Please sign in to comment.