NodeJS同步流

时间:2017-07-04 11:17:01

标签: node.js synchronization

您好我一直在使用名为deasync的库,它允许我以更干净的方式完成工作,我有这样的方法,

syncGetMany: function(model, query){
        var ret;
        setTimeout(function(){

         model.find(query, (error, body) => {
            if(body){
                //Awesome got the data
                ret=  body
            }
            else{

                 //What a cruel world

                // No data, fall back to an empty array
                ret = [];
            }

        });

        },0);
        while(ret === undefined) {
            require('deasync').sleep(0);
        }

        //returns an empty array or the real data
        return ret;    
},

然后我就这样称呼它。

var data = syncGetMany(MongooseModel, queryObj);
// the rest of my code

问题:有没有办法使用ES6或任何类似的库完成此操作。

PS:不重复,因为其他问题与我的背景无关

2 个答案:

答案 0 :(得分:1)

使这段代码更清晰的最简单方法是使用async / await,它可以在node.js中获得版本=> 7.0。如果我认为你的model.find方法会返回promise。

async syncGetMany (model, query) {
    let ret;
    ret = await model.find(query);
    //ret is keeping body from response now, if error occured error is throwed as promise exception
    //Could do some sync ops on ret variable
    return ret;
}

当你使用async / await时,你应该把你的方法执行放到try / catch中。但是你也可以在syncGetMany方法中捕获错误,可能它应该是这样的:

async syncGetMany(model, query) {
    let ret;
    try {
        ret = await model.find(query);
        return ret;
    } catch(err) {
        console.error(err);
        return []; //empty array or any error string/object
    }
}

你的执行看起来像是用额外的await运算符编写的(使用es6为var运算符替换提供let / const运算符) let data = await syncGetMany(MongooseModel, queryObj);

有异步/等待解释的文章: https://blog.risingstack.com/async-await-node-js-7-nightly/

如果您不想使用Node v7.0,您应该使用promises和generator编写类似的代码。

https://medium.com/@rdsubhas/es6-from-callbacks-to-promises-to-generators-87f1c0cd8f2e

我希望我能帮忙。

<强>更新 因此,当您的mongoose实例不支持promise时,有三个选项(取决于我对节点版本的看法)。在我看来,promises是更简洁的异步请求方式所以我建议使用它们。

第一个选项(原生承诺):

syncGetMany(model, query) {
    return new Promise((resolve, reject) => {
        model.find(query, (err, res) => {
            if(err) {
                return reject(err);
            }
            resolve(res);
        });
    });
}

第二个选项(bluebird库,为所有方法添加了Async postfix):

const mongoose = require( 'mongoose' );
const Promise = require('bluebird');
Promise.promisifyAll( mongoose );

async syncGetMany(model, query) {
    let ret;
    try {
        ret = await model.findAsync(query);
        return ret;
    } catch(err) {
        console.error(err);
        return []; //empty array or any error string/object
    }
}

第三个选项(节点版本=&gt; 8.0):

在功能上使用原生promisify: https://nodejs.org/dist/latest-v8.x/docs/api/util.html#util_util_promisify_original

在我们的同步部分(在函数构造之前使用异步运算符): let data = await syncGetMany(MongooseModel, queryObj);

答案 1 :(得分:-1)

您可以使用nsynjs编写和执行逻辑,就好像它是同步的一样:

function synhronousCode(model, query) {
    function syncGetMany(model, query){
        return model.find(query).data; // data will contain result of resolved promise at this point
    };

    var data = syncGetMany(model, query);
    // do stuff with data
}

var nsynjs = require('nsynjs');
....
nsynjs.run(synhronousCode,{},model, query, function(){
    console.log('synhronousCode done');
});

nsynjs将以顺序方式评估synhronousCode中的代码:如果某个函数返回promise(如model.find那样),nsynjs将暂停执行并等待promise被解析,并将结果赋给{{1}返回值的属性,然后继续执行。