jedireza / mongo-models

:package: Map JavaScript classes to MongoDB collections
MIT License
67 stars 28 forks source link

Native Async/Await Support #21

Closed AddoSolutions closed 7 years ago

AddoSolutions commented 7 years ago

Hello,

I am not sure if there is an open issue on this or if I am doing something wrong, but I do not beleive this library properly complies with the NodeJS native async protocol:

Example:


const Goat = require("models/Goat");

async someFunction(){

   var allGoats = await Goat.find({});
   console.log(allGoats); // This returns undefined;

   var nativeGoats = await db.collection("Goats").find({}).asArray();
   console.log(nativeGoats); // Get an [] of all my goats

}

I did some tweaking on my own fork, and found that I could get it working, but I do not know how this plays with compatibility with other versions:


    static resultFactory() {

        const args = new Array(arguments.length);
        for (let i = 0; i < args.length; ++i) {
            args[i] = arguments[i];
        }

        var first = args.shift();
        var next = first,
            resolve = false,
            reject = false;
        if (first && first.forEach && first.length == 4) {
            var [next, resolve, reject] = first;
        }
        if (typeof next !== 'function' || !next || !next.apply) next = false;

        const err = args.shift();
        let result = args.shift();

        if (err) {
            args.unshift(result);
            args.unshift(err);
            if (reject) reject(err);
            if (next) return next.apply(undefined, args);
            return;
        }

        const self = this;

        if (Object.prototype.toString.call(result) === '[object Array]') {
            result.forEach((item, index) => {

                result[index] = new self(item);
            });
        }

        if (Object.prototype.toString.call(result) === '[object Object]') {
            if (result.hasOwnProperty('value') && !result.hasOwnProperty('_id')) {
                if (result.value) {
                    result = new this(result.value);
                } else {
                    result = undefined;
                }
            } else if (result.hasOwnProperty('ops')) {
                result.ops.forEach((item, index) => {

                    result.ops[index] = new self(item);
                });

                result = result.ops;
            } else if (result.hasOwnProperty('_id')) {
                result = new this(result);
            }
        }

        args.unshift(result);
        args.unshift(err);
        if (resolve) resolve(result);
        if (next) next.apply(undefined, args);
    }

…

    static async find() {

        const args = new Array(arguments.length);
        for (let i = 0; i < args.length; ++i) {
            args[i] = arguments[i];
        }

        return new Promise((resolve, reject) => {
            const collection = MongoModels.db.collection(this.collection);

            var cb = false;
            if (typeof args[args.length - 1] == 'function') cb = args.pop();
            const callback = this.resultFactory.bind(this, [cb, resolve, reject, true]);

            collection.find.apply(collection, args).toArray(callback);

        });
    }

Any thoughts on this, feel free to take a peek at my fork, but I am not sure how you would implement this with compatibility.

Nick

jedireza commented 7 years ago

My understanding is the foundation for async/await is promises.

every async function you write will return a promise, and every single thing you await will ordinarily be a promise.

Via: https://medium.com/@bluepnume/learn-about-promises-before-you-start-using-async-await-eb148164a9c8

The idea of uses promises has been brought up before: #6 #20 and in both of those issue I've linked back to https://github.com/jedireza/hapi-mongo-models/issues/6

Like I said in that hapi-mongo-models thread:

I almost never use promises. If it's as simple as mentioned above and doesn't disturb the existing API, a PR is welcomed.

jedireza commented 7 years ago

:mega: Async/await support is on the menu now. Tracked via: https://github.com/jedireza/mongo-models/issues/24 and help is very much appreciated.