Including the JSINQ files

JSINQ consists of two components, jsinq.Enumerable and jsinq.Query. The "Enumerable" component is a complete, API-compatible implementation of the .NET class System.Linq.Enumerable. To use jsinq.Enumerable, you need to include the "jsinq.js" file in your HTML page like this:

<script type="text/javascript" src="jsinq.js"></script>

It is recommended that you use the file found in the "build" folder as it is substantially smaller than the un-minified file found in the "source" folder.

If you also want to use jsinq.Query (see below), you'll also have to include the file "jsinq-query.js".

Writing queries using query-methods

Once you have included the file(s), you can start to write queries against arrays, DOM node lists or your own enumerable objects. An example:

var names = ['Bob', 'Alice', 'Joe', 'Frank', 'Arthur', 'Marcy'];
var enumerable = new jsinq.Enumerable(names);

var namesThatStartWithAnA = enumerable.where(function(name) { 
	return name.charAt(0) == 'A'; 
});

The variable "namesThatStartWithAnA" now refers to an enumerable that will return all the names in the "names" array that start with a capital "A" when enumerated. To enumerate an enumerable, do the following:

var enumerator = namesThatStartWithAnA.getEnumerator();
while (enumerator.moveNext()) {
	var name = enumerator.current();
	document.write(name + '<br />');
}

There is also a convenient helper-method that makes enumerating over the elements in an enumerable much easier:

namesThatStartWithAnA.each(function(name) {
	document.write(name + '<br />');
});

You can create more complex queries by chaining together multiple query-methods like this:

var result = enumerable.where(function(name) { 
	return name.toLowerCase().indexOf('a') > -1; 
}).orderByDescending(function(name) { 
	return name; 
});

When enumerating the enumerator referred to by the variable "result", you will receive a list of all names that contain an "a" in a reverse alphabetical order.

Using this "pattern", you can create arbitrarily complex queries. Unfortunately, the simple query above already looks quite complex and as you keep adding clauses to your query, it will become increasingly difficult to see what the result of a query is going to be.

Writing queries using query expressions

Fortunately, chaining together query-methods is not the only way of defining a query in JSINQ. Instead, you can write your queries in a more natural, SQL-like fashion:

var query = new jsinq.Query(' \
	from name in $0 \
	where name.toLowerCase().indexOf("a") > -1 \
	orderby name descending \
	select name \
');

So what is going on here? The Query constructor provided by JSINQ receives a string containing a LINQ expression and essentially compiles it into JavaScript code. Unsurprisingly, the JavaScript code produced by the query compiler looks exactly like the code in the previous examples. Looking at the code above however, you might notice two things that are weird. For one, what is up with all the backslashes? JavaScript does not officially support multi-line strings which is a bummer, because queries look so much nicer when you put each clause on a separate line. Multi-line strings can however be simulated by placing a backslash at the end of each line. This is slightly evil because it is not in any way mentioned in the JavaScript language specification, but it appears to work in most browsers (read: use with caution and at your own risk). Secondly, what is "$0"? The JSINQ Query object essentially acts like a prepared statement. When you create a new Query object, you invoke the query compiler but the query is not actually executed. That way, you can use the same query many times without having to re-compile it over and over again. What's even better is, that you can apply the same query to different datasets without having to re-compile it. This is where placeholders come into play. You can use placeholders in your query, where you would otherwise use an identifier or an expression. Using the "setValue" method of the Query object, you can then assign a concrete value to each placeholder like this:

query.setValue(0, enumerable);

This assigns our enumerable (the one with the names in it) to placeholder "$0". Once you have assigned a value to each placeholder, you can execute a query by invoking its "execute" method. Our example in its entirety now looks like this:

var query = new jsinq.Query(' \
	from name in $0 \
	where name.toLowerCase().indexOf("a") > -1 \
	orderby name descending \
	select name \
');

query.setValue(0, enumerable);
var result = query.execute();

The variable "result" now contains the enumerable that is the result of applying our query to the enumerable that we have specified using the "setValue" method.

What's next?

Last edited Mar 27, 2010 at 2:17 PM by kaijaeger, version 7

Comments

yangyanghaoran Aug 20, 2013 at 3:44 AM 
I want to know what about the performance of JSINQ?