-
Notifications
You must be signed in to change notification settings - Fork 212
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Async and sync in the same evaluation #77
Comments
Hi Martin. Thanks for raising this. At the moment I am struggling to understand exactly the issue that are describing, so if you could expand with code examples, that would be really useful. I’m wondering if this is an issue with the jsonata language itself, or with the implementation. JSONata is designed as a declarative language and not an imperative language. In other words, the syntax is used to describe the desired result and not the steps a computer has to take to achieve that result. So there is no syntax to control the flow of execution. I only say that because that new syntax you have proposed looks as if its purpose is to control the flow of execution. I also need to mindful of not tying jsonata into only being implementable in javascript. I know of a group who are creating a native implementation in Java. Having said all that, I’m keen to understand the issue further so that we can enable your use-case. |
Hello Andrew. I see jsonata as a json object manipulation tool. With 3 lines of code i could extend to also accept data from a database via an orm. So in fact, I see my database as one gigantic json blob.... Perfect for jsonata. I believe we don't need much imagination to see the power in that. However in some cases then the performance is not that good and being able to use the power of the orm is critical. if you want to build a sql string with an orm, you do something like: meta.build().select("*").from("table") and get an output: "SELECT * FROM "table"". Then at the end of these chained methods you wait for the promise. Now to get that to work, I need to tell jsonata when to wait and when not to. In this case after all functions. In another case however, say: "$meta($first().second)" I would like to retrieve the result after each method, thereby not waiting until the end. Jsonata does the first by standard and the second in my extension, I need both..... Hope this makes sense. |
Sorry one more thing. The first case works perfectly well with vanilla jsonata, so the "imperative" part works very well. It is when I want to mix, I have problems. |
The problem here, I think, is that the knex Let me know if this works for you. |
First of all, tremendous thanks for building this addition, it is of great value here!:-) I made my own tests and confirm that it works as defined in the unit tests. So now we are almost there, there is only one small piece missing and that is to wait for the promise inside the expression. I see that using the standard $count function it does wait for the promise to fulfill before the count is called but this does not seems to work for custom functions... Example: Is there any way to add this functionality also to custom functions? Or add a dummy function to the standard ones? Again many, many thanks for building this. It makes jsonata even more awsome! |
Hmm, that's odd. The following code works for me, could you try running this, please: var jsonata = require('jsonata');
var knex = require('knex')({
client: 'sqlite3',
connection: {
filename: "./mydb.sqlite"
},
useNullAsDefault: true
});
expression = '( $vari := $dummy($knex("business_document").select().where({"id":"1"})); {"return":$vari} )';
var dummy = function(arg) {
console.log('DUMMY', arg);
return arg;
};
var bindings = {
'knex': knex,
'dummy': dummy
};
var expr = jsonata(expression);
var callback = function(err, result) {
if(err) {
console.log('ERROR:', err);
} else {
console.log('Result:', result);
}
};
expr.evaluate({}, bindings, callback); I get the following output:
so the value of |
The difference seems to be that I use async/await. With a callback as in your example above, I get the same result as you. With the following: Can I conclude that I should avoid using async/await and wrap my callback instead? Could this be made to work with async/await? Many, many thanks, Martin |
Hi Martin, var jsonataPromise = function(expr, data, bindings) {
return new Promise(function(resolve, reject) {
expr.evaluate(data, bindings, function(error, response) {
if(error) reject(error);
resolve(response);
});
});
}; Given you now have this working, I'll merge |
Hello Andrew, Speaking about merging, when will the 1.4 be merged as well? That is another extremely useful feature what is tremendously useful for us. Many thanks, Martin |
Hello Andrew, Today I tested with chained method with binding and then it did not go so great: var bindings = {
'knex': knex,
'dummy': dummy
};
var expression = jsonata(`$knex($.table).select().where({"last_name":$.name})`);
expression.evaluate({table:"contract_party", name:"Dumont"},bindings,(err,res)=>{
console.log(err);
console.log(res);
}); In this case table input (contract_party) is picked up correctly but name (Dumont) is evaluated to undefined in the where method. UPDATE: var expression = jsonata(`$knex($.table).select().where({"last_name":$$.name})`); Note that some times when I run the above, the jsonata inside the where method does not get executed, strange error I cannot reproduce anymore. Cheers |
Closing this issue as resolved. Feel free to re-open if you have any more problems with this. |
Hello again. I have another issue I would need some input on.
I work with knex, a sql builder that uses chained methods to build the sql and then at the end uses a promise.
Converted jsonata to work with async/await simply by copy paste whenever it was generator functions. This works reasonably well.
Now I need to use both in the same evaluation, first chain a few methods in sync, run await and then await on all the following expressions.
Could we do a ~([expression]) addition to the syntax or something of the sort to tell jsonata that we should await?
Many thanks
Martin
The text was updated successfully, but these errors were encountered: