Skip to content

Extension to add mongo collection methods to async-methods so they return Extended Promises

License

Notifications You must be signed in to change notification settings

ingenious/am-mongo

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

21 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

AM-MONGO (async-methods mongo extension)

Conveniently-wrapped Mongo collections methods returning ExtendedPromises with async-methods methods available

Methods

The am.mongo extension has two static methods:

am.connect()

  • create persistent application-wide connection

am.close() close persistent connection

The am.mongo extension has the following chainable methods:

All async-methods ExtendedPromise methods are available to manipulate returned and rejected values

See async-methods for full API

Chainable methods

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. When creating chains with am and ExtendedPromise methods always have an

	  .error(err=>{
	
	  }) 

or

	  .catch(err=>{
	
	  })  

at the end of the chain (see examples below). That way errors will be trapped and not cause exceptions

Install

Use versions 0.0.5 and above

                                                                                    
    $ npm install am-mongo@>=0.0.16

Usage

                                                                                    
  let am=require('am-mongo')
    

or

                                                                                    
  let am=require('async-methods')
  
  am.extend('am-mongo')
    

In latter case [email protected] or higher and [email protected] or higher both need to be in package.json

  • Can have single database conenction per application or multiple connections
  • supports mongodb driver 2.3.x and 3.0.x

am.connect() (One persistent connection)

                                                                                    
    // pass url of database and name of dataase to connect()

    testDB = am.connect('dbadmin:[email protected]:27017', 'test').then(db => {

        // db is available once connected

    })

   // or use testDB
        testDB.collections().then(list=>{

            console.log(list)
            // ['location','user']
        })

    am.close()  // closes the connection
    

The same connection will be available in any new chain initiated with am even in sparate modules, so can be used throughout an application.

If needed db and MongoClient are available any time as am.db and am.client

am().connect() (Separate Connection for lifetime of a chain)

                                                                                    
    // pass url of database and name of dataase to connect()
	testDB = am().connect(url, 'test').then(db => {

        // db is available once connected


    })

     // or use testDB (Extended Promise)
        testDB.collections().then(list=>{

            console.log(list)
            // ['location','user']
        })

    testDB.db() // reference to native db object (for other methods if needed)
    testDB.client() // reference to native MongoClient object (for other functions if needed)

    testDB.close()  // close the connection
    

If needed db and MongoClient are available any time as testDB.db() and testDB.client()

.collections()

List a set of collection objects

An array of collections is resolved in by the returned ExtendedPromise

                                                                                    
 testDB
      .collections()
      .map(collection => {
        return collection.collectionName
      }).next(names=>{
          console.log(names)
          // ['location','user','account']
      })
      

.collection(collectionName)

Retrieve a collection object

                                                                                    
     am(function*(){
         let collection= yield testDB.collection('user')
        return collection

     }).then(collection=>{


     })
     

.collectionNames()

Retrieve an array of collection names

List a set of collection names using collectionNames()

                                                                                    
     am(function*(){
         let collectionNames= yield testDB.collectionNames()
        return colelctionNames

     }).forEach(name=>{

         console.log(name) // 'location' 'user' 'bank'

     })
     

.count()

Retrieve a count of documents in a collection

Get a count of records in a collection

                                                                                    
     am(function*(){
         let n= yield testDB.count('user')()
        return n

     }).log() // 2301
     

createIndex(collectionName)((keys, options)

Retrieve a count of documents in a collection

                                                                                    

     am(function*(){
        return yield testDB.insert('location')({
                city: 'London',
                postcode: 'W1A 7YT',
                geo: {
                  type: 'Point',
                  coordinates: [-0.2416813, 51.5285582]
                }
              })
              yield testDB.insert('location')({
                city: 'New York',
                postcode: '3456783',
                geo: {
                  type: 'Point',
                  coordinates: [-73.856077, 40.848447]
                }
              })
         testDB.createIndex('location')({ geo: '2dsphere' })

     }).next(result=>{

         console.log('result')  // 'geo_2dsphere'

     }).catch(err=>{

     })
     

.client()

Returns reference to nodeJS driver native MongoClient object

NB: This returns when using single chain connection method (am().connect()) This method returns a MongoClient object not an ExtendedPromise

                                                                                    
     testDB = am().connect(url, 'test')

     testDB.next(()=>{
        client = testDB.client()
        client.close()

     }
     

.db()

Returns reference to nodeJS driver native database object

NB: This returns when using single chain connection method (am().connect()) This method returns a DB object not an ExtendedPromise

                                                                                    
     testDB = am()
      .connect(url, 'test')
     testDB.next(()=>{
        db = testDB.db()
        collection = db.collection('user')
     }
     

.deleteOne(collectionName)(criteria, options)

Delete one document

                                                                                    
     testDB
          .deleteOne('user')({ name: 'Max' }).log()  // { n: 1, ok: 1 }
          

.deleteManycollectionName)(criteria, options)

Delete one or more documents

                                                                                    
        testDB.deleteMany('user')({ balance: { $lt: 8900 } })
        .log()  //  { n: 2, ok: 1 }

.distinct(collectionName)()

Get a list of unique values for an attribute

                                                                                    
      testDB.distinct('user')('name')
      .log()  //   [ 'Max', 'Mary' ]
      

.dropCollection((collectionName))

drop of a collection

                                                                                    
      testDB.dropCollection('user')
      .log()  //  true
      

.findOne(collectionName)(criteria, options)

retrieve a single document

                                                                                    
   testDB
      .findOne('user')({ name: 'Max' }, { projection: { name: 1, balance: 1 } })
      .log()  // { _id: 5a3b9abec6572e2a7d761420, name: 'Max', balance: 4567 }
      

.find(collectionName)(criteria, options)

retrieve one or more documents

                                                                                    
    testDB
      .find('user')({ name: 'Max' }, { projection: { name: 1, balance: 1 } })
      .log(137)
        //   [ { _id: 5a3b9b1cf418082a9d8a0812, name: 'Max', balance: 4567 }, 
        //       { _id: 5a3b9b1cf418082a9d8a0813, name: 'Max', balance: 1234 } ]
        

.geoNear(collectionName)(x,y,options)

retrieve one or more documents using location proximity

                                                                                                                                                                          
  testDB
      .geoNear('location')(0.2, 51, { spherical: true, maxDistance: 0.1 })
      .log()

      /*
       { results: [
           { dis: 0.010410013646823974,
             obj: { _id: 5a3b9c6888b43f2adddc85c1,
                    city: 'London',
                    postcode: 'W1A 7YT',
                    geo: { type: 'Point', coordinates: [Array] }
             }
         }],
         stats: { nscanned: 3,
                  objectsLoaded: 1,
                  avgDistance: 0.010410013646823974,
                  maxDistance: 0.010410013646823974,
                  time: 0
                },
         ok: 1 }
     */
     

.insertOne(collectionName)(data,options)

insert one document into a collection and return inserted record

                                                                                    
    testDB
      .insertOne('user')({ name: 'Max', balance: 4567 })
      .log()   //  { name: 'Max', balance: 4567, _id: 5a3b9d26cfaaae2b05ba243a }
      

.insert(collectionName)(data,options)

insert one or more documents into a collection and return inserted records

                                                                                    
    testDB
      .insert('user')([{ name: 'Max', balance: 1234 }, { name: 'Mary', balance: 8971 }])
      .log()
        //  [ { name: 'Max', balance: 1234, _id: 5a3b9d93169eeb2b24246bf0 },
        //    { name: 'Mary', balance: 8971, _id: 5a3b9d93169eeb2b24246bf1 } ]
        

.isCollection(collectionName)

Check if collection exists

                                                                                    
    testDB
      .isCollection('user')
      .next(boolean => {
        console.log(boolean) // true
      })
      

options(collectionName)

Get options of collection

                                                                                    
 testDB
      .options('user')
      .next(config => {
        console.log(config) // {}
      })
      

.rename(collectionName)(newName)

Rename a collection

                                                                                    
 testDB
      .rename('balance')('bank')
      .next(function*(collection) {
        let banks = yield testDB.find('bank')(),
          balances = yield testDB.find('balance')()
        console.log(collection.collectionName,balances.length,banks.length)  //  'bank', 0, 2

      })
      

updateOne(collectionName)(criteria, update, options)

Update one document

                                                                                    
        testDB
          .updateOne('user')({ name: 'Max' }, { balance: 7777 })
          .log()    //   { n: 1, nModified: 1, ok: 1 }
          

update(collectionName)(criteria, update, options)

Update one or more documents

                                                                                    
        testDB
          .update('user')({ name: 'Max' }, { balance: 8888 })
          .log()    //  { n: 2, nModified: 2, ok: 1 }
          

upsert(collectionName)(criteria, update, options)

Upsert (Amend if exists, create if not) one or more documents

                                                                                    
        testDB
          .upsert('user')({ name: 'Max' }, { balance: 8888 })
          .upsert('user')({ name: 'Molly' }, { name: 'Molly', balance: 2222 })
          .log()
          //    { n: 1, nModified: 0,  
          //      upserted: [ { index: 0, _id: 5a3ba7201c12d25fdd112353 } ],
          //      ok: 1 }
          

upsertOne(collectionName)(criteria, update, options)

Upsert (Amend if exists, create if not) one document

                                                                                    
        testDB
          .upsertOne('user')({ name: 'Max' }, { balance: 7777 })
          .log()  // { n: 1, nModified: 1, ok: 1 }
          

Tests

There are 210 automated tests for this extension in /tests. The test suites illustrate repeated operations on same database.

                                                                                            
    $  npm test

    # test mongo methods only
    $ npm run test-mongo

    # test base async-methods methods (ExtendedPromise methods)
    $ npm run test-am
    

Appendix

Chainable Methods for manipulating and logging data

In all cases fn can be a generator or a normal function (for analagous synchronous operation) An ES6 Class (anon or nameed) can be used using syntax .next(methodName,class). This gives access to async/await

An optional tolerant argument can be used with .map() or .filter() or with .mapFilter() to ensure completion even if there is an error


Chainable Methods

In all cases fn can be a generator or a normal function (for analagous synchronous operation) An ES6 Class (anon or nameed) can be used using syntax .next(methodName,class). This gives access to async/await

An optional tolerant argument can be used with .map() or .filter() or with .mapFilter() to ensure completion even if there is an error

map

.map(fn,tolerant)

fn can be a normal function (synchronous operations) or a generator (asynchronous operations)

equivalent to .map(). If the previous stage of the chain resolves to an array or object, each element of the array or object is replaced with the returned result of the function or generator

map with function (synchronous step)

                                                                                      
am(Promise.resolve([45, 67]))
  .map(function (item) {
    return item / 10;
  })
  
  .log('map Promise result') // map Promise result  [ 4.5, 6.7 ]​​​​​
  
  .error(err=>{      
      		// handle errors at end of chain
      
  })
  

map with anonymous class and async/await

                                                                                      
     am([4, 5, 6])
        .map(
          'asyncMap',
          class {
            async asyncMap(value) {
              return await Promise.resolve(2 * value)
            }
          }
        )
        .map(
          'syncMap',
          class {
            syncMap(value) {
              return 3 * value
            }
          }
        )
        .log()   //  [24, 30, 36]
        
        .error(err=>{      
      		// handle errors at end of chain
         })
  

filter

.filter(fn, tolerant)

fn can be a normal function (synchronous operations) or a generator (asynchronous operations) An ES6 Class (anon or named) can be used using syntax .filter(methodName,class).

*Filter can be applied to objects and other entitites as well as arrays

filter with function (synchronous step)

                                                                                      
  am(7).filter(function (value) {
    return 7 - value;
  })
  .log() // null
  .error(err=>{      
     // handle errors at end of chain
      
  })
  

filter with generator/yield

                                                                                      
  am(7).filter(function* (value) {
     return yield(8 - value);
  })
  
  .log() // 7
  
  .error(err=>{      
      		// handle errors at end of chain
      
  })
  

fiter with async/await

                                                                                      
     am({ a: 4, b: 5, c: 6 })
        .filter(
          'asyncMap',
          class {
            async asyncMap(value, attr) {
              return await Promise.resolve(value < 5 ? false : true)
            }
          }
        )
        .filter(
          'syncMap',
          class {
            syncMap(value, attr) {
              return value === 6 ? false : 2 * value
            }
          }
        )
        
        .log()    // {b:5}
        
        .error(err=>{      
      		// handle errors at end of chain
      
        })
  

filter with object input

                                                                                      
  am({
      a: 27,
      b: 78
  }).filter(function* (value, attr) {

    let a = yield Promise.resolve(value);
    return a > 50;
  })
  
  .log() //   { b: 78 }​​​​​
  
  .error(err=>{      
  		// handle errors at end of chain
      
  })
  

mapFilter

.mapFilter(fn, tolerant)

Combines a map followed by a fiter using values returned from the map If the mapping function for an element returns false, then the element is excluded from the result

fn can be a normal function (synchronous operations) or a generator (asynchronous operations). An ES6 Class (anon or named) can be used using syntax .mapFilter(methodName,class).

mapFilter with function (synchronous step)

                                                                                      
     am([3, 4, 5])
       .mapFilter(function (value, i) {
         let a= 2 * value + i;
         return a > 6 ? a :false;
       })
       
       .log()     //   [ 9, 12 ]​​​​​
       
       .error(err=>{      
      		// handle errors at end of chain
      
       })
  

mapFilter with anonymous class

                                                                                      
    am([4, 5, 6])
        .mapFilter('asyncMap', class {
            async asyncMap(value) {
              return value < 5 ? false : await Promise.resolve(2 * value)
            }
          })
        .mapFilter('syncMap', class {
            syncMap(value) {
              return value === 10 ? false : 2 * value
            }
          })
        .log()  // [24]
        
         .error(err=>{      
      		// handle errors at end of chain
      
         })
  

forEach

.forEach(fn)

fn can be a normal function (synchronous operations) or a generator (asynchronous operations). An ES6 Class (anon or named) can be used using syntax .forEach(methodName,class).

forEach returns an extended Promise resolving to the initial array or objectx

forEach with function (synchronous step)

                                                                                      
    am([34, 56, 78]).forEach(function (value, i) {
           console.log(value, i);
    })
    
    .log()  // 34 0, 56 1, 78 2, [34, 56, 78]
    
    .error(err=>{      
      		// handle errors at end of chain
      
    })
  

forEach with generator/yield (asynchronous steps)

                                                                                      
  am([34, 56, 78]).forEach(function* (value, i) {
     console.log(yield am.resolve(2 * value),i);
  })
  
  .log() // 68 0, 112 1, 156 2
  
  .error(err=>{      
      // handle errors at end of chain
      
  })
  

forEach with class and async/await

                                                                                      
    let test = []
      am(66)
        .forEach('asyncMap', class {
            async asyncMap(value, i) {
              test.push(await Promise.resolve(value))
            }
          }
        )
        
        .forEach('syncMap',class {
            syncMap(value, i) {
              test.push(2 * value)
            }
          })
          
        .next(function(){
                
            console.log(test)  // [66,132]
        })
        
        .error(err=>{      
      		// handle errors at end of chain
      
       })
  

forEach with Object input

                                                                                      
   am({
     a: 34,
     b: 56,
     c: 78
   })
   
   .forEach(function* (value, attr) {
        console.log(yield am.resolve(3 * value), yield am.resolve(attr));
		 // ​​​​​102 'a'​​​​​, 168 'b'​​​​​, 234 'c'​​​​​ 

   })
   
   .log() // { a: 34, b: 56, c: 78 }​​​​​
   
   .error(err=>{      
      		// handle errors at end of chain
      
       })
   
  

next

.next(fn)

fn can be a normal function (synchronous operations) or a generator (asynchronous operations). An ES6 Class (anon or named) can be used using syntax .next(methodName,class).

next with anonymous class

                                                                                      
     am(56)
        .next('test', class {
            async test(value) {
              return await Promise.resolve(89 + (value || 0))
            }
          })
        
        .log()    //  145
        
        .error(err=>{      
      		// handle errors at end of chain
      
       })
  

next with named class

                                                                                      
      let sample = class {
        async test(value) {
          return await Promise.resolve(89 + (value || 0))
        }
      }
      let ep = am(56)
        
        .next('test', sample)
        
        .log()   //145
        
        .error(err=>{      
      		// handle errors at end of chain
      
       })
  

next with newed Class

                                                                                      
    let sample = class {
        constructor(type) {
          this.type = type
        }
        async test(value) {
          return await Promise.resolve(89 + (this.type || 0) + (value || 0))
        }
      }
      let ep = am(56)
        .next('test', new sample(45))
        .next(r => {  
          console.log(r)        // 190  (45 + 89 + 56)
          
        })
        
        .error(err=>{      
      		// handle errors at end of chain
      
        })
  

prev

.prev()

returns ExtendedPromise resolving or rejecting per previous step in chain

The ExtendedPromise object keeps a reference to all previous states of the specific chain. prev() uses this to allow the application logic to reverse the chain to previous states

prev() after map()

                                                                                      
                                                                                      
    let ep = am(function*() {
          yield Promise.resolve()
          return { a: 238 }
        })
        .map(function(value, attr) {
          return value * 2
        })
    
        .prev()
        
        .next(r => {
          console.log(r) // { a: 238 })
          
        })
        .error(err => {
          // handle errrors at end of chain
        })

prev() used twice

                                                                                      
    let ep = am(function*() {
        yield Promise.resolve()
        return { a: 238, b: 56 }
      })
        .map(function(value, attr) {
          return value * 2
        })
        .filter(function(value, attr) {
          return attr === 'a' ? true : false
        })
        .prev()
        .prev()
        .next(r => {
          console.log(r) // { a: 238, b: 56 })
          
        })
        .error(err => {
          	// handle errors at end of chain
        })

prev() after map() and wait()

                                                                                      
      let ep = am(function*() {
          yield Promise.resolve()
          return { a: 238, b: 56 }
        })
        .map(function(value, attr) {
          return value * 2
        })
        .wait(200)

        .prev()

        .next(r => {
          console.log(r) // { a: 238, b: 56 })
          
        })
        .error(err => {
          
        })

prev() after error()

                                                                                      
 let ep = am.reject({ error: 89 })
 		  .error(()=> {
           return { b: 789 }
        })
      
        .prev()
        .error(r => {
          console.log(r) // { error: 89 })
          
        })

twoPrev

.twoPrev(fn)

fn can be a normal function (synchronous operations) or a generator (asynchronous operations). An ES6 Class (anon or named) can be used using syntax .twoPrev(methodName,class).

twoPrev with function (synchronous step)

      let ep = am([5, 6, 7])
        .next(function(item) {
          return { a: 2 }
        })
        .next(function(item) {
          return { b: 3 }
        })
        .twoPrev((lastResult, previousResult) => {
        
        console.log(lastResult, previousResult)
          // { b: 3 } { a: 2 }

          
        })
        .error(err => {
          
        })

twoPrev wiith anonymous class

                                                                   
      let ep = am(56)
        .next(function(item) {
          return { a: 2 }
        })
        .twoPrev(
          'test',
          class {
            async test(value, previous) {
              console.log(value,previous) // { a: 2 } 56
              return await Promise.resolve(89 + (previous || 0))
            }
          }
        )
        .next(r => {
          console.log(r) //  145
          
        })
        .error(err => {
          // handle errors
        })                                                                          
    
  

twoPrev with named class

Illustrates Asyncronous steps in ES6 Class pattern

   let ep,
        sample = class {
        
        	// async method
          async test(value) {
            return await Promise.resolve(89 + (value || 0))
          }
          
          // generator method
          *result(result, previous) {
           console.log(result, previous) // 145, 56
            
          }
        }
      ep = am(56)
      
        // adds result to chain
        .next('test', sample)  
        
        // result and previous passed to result method
        .twoPrev('result', sample)         
        
        .error(err => {
        	// handle errors  
        
        })
                                                                                      
       

twoPrev with generator

                                                              
let ep = am([5, 6, 7])

		// add result to chain
        .next(function*(item) {
          return yield { second: 897 }
        })
        .twoPrev(function*(result, prev) {
          console.log(result, prev)  //{ second: 897 }  [5, 6, 7]
        })
      
        .next(result => {
          console.log(result) // [{ second: 897 }, [5, 6, 7]]
          
        })
        .error(err => {
          // handle errors
          
        })

twoPrev with newed Class

   let ep, 
   sample = class {
 
       constructor(type) {
          this.type = type
       }
       
       async test(value) {
         return await Promise.resolve(89 + (this.type || 0) + (value || 0))
       }
       
       *result(r, p) {
         console.log(r, p) //  190, 56
       }
   },
 
   newed = new sample(45)

      ep = am(56)
        .next('test', newed)
        .twoPrev('result', newed)
        .next(result => {
          console.log(result)  // [190, 56]
          
        })
        .error(err => {
          // handle errors
          
        })
         

threePrev

.threePrev(fn)

fn can be a normal function (synchronous operations) or a generator (asynchronous operations). An ES6 Class (anon or named) can be used using syntax .twoPrev(methodName,class).

threePrev with function

      let ep = am([5, 6, 7])
        .next(function(item) {
          return { a: 2 }
        })
        .next(function(item) {
          return { b: 3 }
        })
        .threePrev((lastResult, previousResult, previous) => {
        
           console.log(lastResult, previousResult, previous)
           // { b: 3 } { a: 2 } [5,6,7]
        })
        
        .error(err => {
        	// hanlde errors at end of chain  
        })

threePrev wiith anonymous class

                                                                   
      let ep = am(56)
        .next(function(item) {
          return { b: 3 }
        })
        .next(function(item) {
          return { a: 2 }
        })
        .threePrev(
          'test',
          class {
            async test(value, previous, first) {
              console.log(value,previous) // { a: 2 } {b:3}  56
              return await Promise.resolve(89 + (first || 0))
            }
          }
        )
        .next(r => {
          console.log(r) //  145
          
        })
        .error(err => {
          // handle errors
        })                                                                          
    
  

threePrev with named class

Illustrates Asyncronous steps in ES6 Class pattern

   let ep,
        sample = class {
        
        	// async method
          async test(value) {
            return await Promise.resolve(89 + (value || 0))
          }
          
          // generator method
          *result(result, previous, first) {
           console.log(result, previous, first) // 188, 99, 56
            
          }
        }
      ep = am(56)
      
      	  // add result to chain
        .next(r=>{
      		return 99;
        })
      
        // adds result to chain using named class
        .next('test', sample)  
        
        // result and previous passed to result method
        .threePrev('result', sample)         
        
        .error(err => {
        	// handle errors  
        
        })
        
    
                                                                                      
       

threePrev with generator

                                                              
let ep = am([5, 6, 7])

		// add result to chain
        .next(r=>{
      		return 99;
        })

		// add result to chain
        .next(function*(item) {
          return yield { second: 897 }
        })
        .threePrev(function*(result, prev, first) {
          console.log(result, prev, first)  // { second: 897 } 99 [5, 6, 7]
        })
      
        .next(result => {
          console.log(result) // [{ second: 897 }, 99, [5, 6, 7]]
          
        })
        .error(err => {
          // handle errors
          
        })

threePrev with newed Class

 let ep, 
 sample = class {
 
       constructor(type) {
          this.type = type
       }
       async test(value) {
         return await Promise.resolve(89 + (this.type || 0) + (value || 0))
       }
       
       *result(r, p, f) {
         console.log(r, p, f ) //  233, 99, 56
       }
 },
 
 newed = new sample(45)

      ep = am(56)
        
        // add results to chain
        .next(()=>{
      		return 99;
        })
        .next('test', newed)
        
        // invoke method with 3 previous resolved values
        .threePrev('result', newed)
        .next(result => {
          console.log(result)  // [233, 99, 56]
          
        })
        .error(err => {
          // handle errors
          
        })
            

timeout

.timeout(ms)

                                                                                      
    am.waterfall([
      am.resolve(999).timeout(2000),
      am.resolve(8).timeout(1000)
    ])
    
    .log() // [2002ms] [ 999, 8 ]​​​​​
    
    .error(err=>{      
      		// handle errors at end of chain
      
     })
  

wait

alias of .timeout()

.wait(ms)

                                                                                      
      am.sfFn(sf, 1).wait(3000)
      
      .log('wait')  // ​​​​​wait [3003ms] 1​​​​​
      
      .error(err=>{      
      		// handle errors at end of chain
      
       })

log

.log(<success label>[,<error label>'[,Error()]])

Adding Error() as last attribute will allow log to add the line number and filename to log of success values as well as errors

                                                                                      
  am.sfFn(sf, 1).wait(3000)
    
    .log('with line no. ', Error());
    // ​​​​​with line no.   line 12  of async-methods/test-4.js 1​​​​​
  
    .error(err=>{      
      		// handle errors at end of chain
      
    })

error

.error(fn)

Similar to .catch() but by default it is 'pass-through' ie if nothing is returned - the next stage in the chain will receive the same result or error that was passed to error(fn).

fn can also be a normal function or a generator allowing a further chain of asyncronous operations. An ES6 Class (anon or named) can be used using syntax .error(methodName,class).

If the function or generator returns something other than undefined or an error occurs that result or error will be passed to the next stage of the chain.

                                                                                      
   am.waterfall({
      a: am.reject(88),
      b: function (result, cb) {
        result.f = 567;
        cb(null, 444 + result.a);
    },
      c: function (result, cb) {
      cb(null, 444 + result.a + result.b);
     }
   })
   .error(function (err) {
     
     return am.reject(new Error('no good'))
  })
  
  .log('waterfall object', 'waterfall err')
  // ​​​​​waterfall err [Error: no good]​​​​​
  
  .error(err=>{      
      		// handle errors at end of chain
      
  })

promise

.promise()

Converts an Extended Promise to a normal promise (with methods catch and then)

                                                                                      
   am([2, 3, 4]).next(function () {}).log()
      
      .promise()
      
      // chain is now native promise
      .then(function (result) {
      
          console.log('Promise resolves with', result);
          // Promise resolves with [2,3,4]
          
      }).catch(function (err) {
          
          // handle errors with catch() not error()
          console.log(err);
      });
   //logs
   
   

then

.then(fn)

Similar to **.then() but returns an Extended Promise.

If want fn to be a generator use .next()

catch

.catch(fn)

Identical to .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.


About

Extension to add mongo collection methods to async-methods so they return Extended Promises

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published