How to use “q” module for refactoring mongoose code?

后端 未结 5 506
野趣味
野趣味 2020-12-31 04:30

I\'m using mongoose to insert some data into mongodb. The code looks like:

var mongoose = require(\'mongoose\');
mongoose.connect(\'mongo://localhost/test\')         


        
5条回答
  •  难免孤独
    2020-12-31 04:51

    Two years later, this question just popped up in my RSS client ...

    Things have moved on somewhat since May 2012 and we might choose to solve this one in a different way now. More specifically, the Javascript community has become "reduce-aware" since the decision to include Array.prototype.reduce (and other Array methods) in ECMAScript5. Array.prototype.reduce was always (and still is) available as a polyfill but was little appreciated by many of us at that time. Those who were running ahead of the curve may demur on this point, of course.

    The problem posed in the question appears to be formulaic, with rules as follows :

    • The objects in the array passed as the first param to conn.collection(table).insert() build as follows (where N corresponds to the object's index in an array):
      • [ {}, ... ]
      • [ {userId:userN._id}, ... ]
      • [ {userId:userN._id, channelId:channelN._id}, ... ]
    • table names (in order) are : users, channels, articles.
    • the corresopnding object properties are : user, channel, article (ie the table names without the pluralizing 's').

    A general pattern from this article by Taoofcode) for making asynchronous call in series is :

    function workMyCollection(arr) {  
        return arr.reduce(function(promise, item) {
            return promise.then(function(result) {
                return doSomethingAsyncWithResult(item, result);
            });        
        }, q());
    }
    

    With quite light adaptation, this pattern can be made to orchestrate the required sequencing :

    function cascadeInsert(tables, n) {
        /* 
        /* tables: array of unpluralisd table names
        /* n: number of users to insert.
        /* returns promise of completion|error
         */
        var ids = []; // this outer array is available to the inner functions (to be read and written to).
        for(var i=0; i

    Lastly, here's the promise-returning worker function, insert() :

    function insert(ids, t) {
        /* 
        /* ids: array of plain objects with properties as defined by the rules
        /* t: table name.
        /* returns promise of docs
         */
        var dfrd = Q.defer();
        conn.collection(t).insert(ids, function(err, docs) {
            (err) ? dfrd.reject(err) : dfrd.resolve(docs);
        });
        return dfrd.promise;
    }
    

    Thus, you can specify as parameters passed to cascadeInsert, the actual table/property names and the number of users to insert.

    cascadeInsert( ['user', 'channel', 'article'], 2 ).then(function () {
       // you get here if everything was successful
    }).catch(function (err) {
       // you get here if anything failed
    });
    

    This works nicely because the tables in the question all have regular plurals (user => users, channel => channels). If any of them was irregular (eg stimulus => stimuli, child => children), then we would need to rethink - (and probably implement a lookup hash). In any case, the adaptation would be fairly trivial.

提交回复
热议问题