orientechnologies / orientjs

The official fast, lightweight node.js client for OrientDB
http://orientdb.com
Other
326 stars 67 forks source link

Feature Request - Synchronous Queries #70

Open TeamXceleratorDev opened 9 years ago

TeamXceleratorDev commented 9 years ago

Though asynchronous calls have their merit, I would like to encourage the addition of synchronous methods. I see the async-only API to be a barrier to adoption at work. When you have already complicated business logic in service code, adding the promises just complicates things. Can you please, please add synchronous option?

seeden commented 9 years ago

you can use async.waterfall or async.series from async library

hilkeheremans commented 9 years ago

Yes, what @seeden says, or you could consider using promises in combination with ES6 generators which will help you keep things much simpler so far as async programming goes.

StarpTech commented 9 years ago

This is no issue and no enhancement it is up to you. Promises are just an interface to handle with asychronous code in js. Here you can find lots of helper functions https://github.com/petkaantonov/bluebird/blob/master/API.md

Look at this issue: https://github.com/petkaantonov/bluebird/issues/134 There is a method 'each' which can handle the same behaviour of async.series.

or

bluebird extension https://github.com/matthiasg/bluebird-as

TeamXceleratorDev commented 9 years ago

Thanks for the replies, but I think you misunderstood my post. I have used Async and promises before to implement Orient with NodeJS. Besides JS, I also use Java and .Net. If you see the Java API, which is synchronous, you will notice how simple the code becomes. When implementing high-volume, complex business logic, having the synchronous option is very powerful. I have used Async and promises in JS to get the job done before, but it's messy. Providing an optional synchronous API would make life easier for many developers who could then write cleaner code. That is purpose of this feature request. Thanks for the replies and links :)

hilkeheremans commented 9 years ago

@TeamXceleratorDev Assuming I did understand your original post, I agree with you on that promises are messy. I would still advise you to check out what I suggested earlier on either using ES6 generators with promises or using ES7 async functions. You may just end up with what you're looking for, since you would be able to write async code and logic in a very easy to read way.

Take the following original example from the Orientjs README:

db.select().from('OUser').where({status: 'ACTIVE'}).fetch({role: 5}).all()
.then(function (users) {
    console.log('active users', users);
});

with ES7 async functions, this can become

try {
    let users = await db.select().from('OUser').where({status: 'ACTIVE'}).fetch({role: 5}).all()
    console.log('active users', users)
} catch(e) {
    // do something with the error
}

That's right, in this case you can also easily catch whatever exception orientjs throws at you. And you can just as easily iterate over orientjs database calls. Everything happens pretty much in the order that you read it.

Check out this post over at PouchDB, which sums up the problem & solution (at least ES7-wise). If you're not up for using a draft spec, then look up ES6 generators in combination with promises (bluebird's coroutine() function fits excellently), which will accomplish the same thing.

Apologies for linking to another database, but they do explain the issue well.

StarpTech commented 9 years ago

@TeamXceleratorDev java is not javascript. You have to work with the asynchronous model in this way. ES7 async function are much more readable and will make it easier but is still in the "proposal" stage. This feature request could be great for the future until now promises are the only way which can simplify the work with the callback hell and they are production ready.

Or you want somehting like this?

var result = db.select().from('OUser').where({status: 'ACTIVE'}).fetch({role: 5}).syncAll()
for(var i .....
optimuspaul commented 9 years ago

I'm finding that things would be so much easier if I could do synchronous things with orient, like I'm creating multiple vertexes and then edges between them. I can't really do that in an async series because I need the results of the first two to do the third. My real world example is a bit more complex than that, but you get the idea. Trying to make it work with promises though.

wizrd commented 9 years ago

@optimuspaul What you're describing isn't an issue achieving using promises. Just return whatever result you want as a promise down the chain to be consumed?

sumpton commented 9 years ago

@optimuspaul this is a typical use case of every programming language, including Javascript and Node.js. Having trouble learning asynchronous programming is also pretty normal, but once you "get it", it is pretty wonderful, and very easy. I would be very surprised if the orientjs contributors were to provide "sync" versions. I don't think they would be used very often.

We use the async module a lot because it keeps our code pretty and is fun to use, but lots of other teams use promises by using other modules.

This explains how to write your code without additional modules http://book.mixu.net/node/ch7.html

It really does not matter how convoluted your requirements are, asynchronous programming is up to the task, and pretty easy to write. It is typically simpler to avoid nesting with functions and callbacks, but the async module will help us synchronous humans write the code in sequential blocks.

optimuspaul commented 9 years ago

@wizrd yes, that's what I'm doing, it's getting ugly but it works. It would just be cleaner if it were synchronous, or could have a transaction associated with it.

@sumpton I know you are trying to be helpful, but your comment just sounds condescending. I am well versed in asynchronous programming. But thanks anyway!

TeamXceleratorDev commented 9 years ago

I agree with @optimuspaul points. I know how to use Async and have done so before. However, the code can get messy when implementing complex business logic including 3rd party calls. A synchronous option (don't have to use it if you don't want to), would help simplify developers working on more complex services.

wizrd commented 9 years ago

@TeamXceleratorDev @optimuspaul A sync option isn't viable unless you're doing a shell script like solution. Sync operations are blocking, and shouldn't be used. If I'm not mistaken *Sync functions are even deprecated io.js, and will be in node v4 (if not removed at that point).

Now, if you want sync-like syntax, what @sumpton wrote is a good solution. There's alternatives (such as BabelJS). You could wrap the Promise in a co-routine and use ES6 generators to yield for a cleaner approach if you don't want to go the ES7 route.

StarpTech commented 9 years ago

I think the root problem here is NodeJs. It is built on top of an asynchronous model. You can use the Java, Groovy, Scala, PHP,.... library. In nodejs I solve the problem with transactions with which you can execute more than one query in a step.

https://gist.github.com/StarpTech/ca0f923c49fd956c1c13