The goal of this recipe is to show us how we can work directly with AJAX requests and load content from different data sources on the same vector layer.
OpenLayers allows us to read data from different origins and sources. We've seen that we can connect to a variety of services (such as WMS and WFS) and/or customize the request according to our needs (such as providing a URL directly pointing to a GML file).
We've seen that providing a URL and format type to the vector source is convenient and works for many cases. OpenLayers makes the AJAX request for us and automatically formats the response. However, there are times when we need even more control over the AJAX request and response, and this is where the loader function comes into play.
We have chosen to use jQuery to perform the AJAX requests. The requests will pull in two separate geometry files of different formats and add them both to the same vector layer. The source code for this recipe can be found in ch03/ch03-reading-features-from-ajax/. Here's the resulting geometry that we'll collate and render on the map:

Create your custom AJAX loader using the following instructions:
div element to hold the map.map, add a raster layer, and center the viewport:var map = new ol.Map({
view: new ol.View({
zoom: 7,
center: [-9039137, 3169996]
}),
target: 'js-map',
layers: [
new ol.layer.Tile({
source: new ol.source.Stamen({layer: 'terrain'})
})
]
});var vectorLayer = new ol.layer.Vector({
source: new ol.source.Vector({
loader: function() {
$.ajax({
type: 'GET',
url: 'points.wkt',
context: this
}).done(function(data) {
var format = new ol.format.WKT({splitCollection: true});
this.addFeatures(format.readFeatures(data));
});
$.ajax({
type: 'GET',
url: 'polygons.json',
context: this
}).done(function(data) {
var format = new ol.format.GeoJSON();
this.addFeatures(format.readFeatures(data));
});
}
})
});map:map.addLayer(vectorLayer);
Let's get straight to it and break down the important parts of this recipe:
source: new ol.source.Vector({
loader: function() {We use the loader property of the vector source to provide a custom function of type ol.FeatureLoader. Similar to the url property (which takes a function type of ol.FeatureUrlFunction), the loader function is also passed extent, resolution, and projection, respectively. We've omitted these as we don't make any use of them for our requests.
$.ajax({
type: 'GET',
url: 'points.wkt',
context: thisWith the help of jQuery, we set up an HTTP GET request, pointing towards a local geometry file, packed with points in the WKT format.
Within the loader function, the this keyword in JavaScript points to the vector source. We intend to use this reference when we add the returned features to the source from within the AJAX promise (done). jQuery offers a useful property called context that enables us to specify what the value of this references in the callbacks or promises. This saves us writing temporary variables or referencing the vector source in another way.
}).done(function(data) {
var format = new ol.format.WKT({splitCollection: true});
this.addFeatures(format.readFeatures(data));
});Once the AJAX request has responded with success, our done promise is fired. The data parameter contains the content of the WKT file.
When the WKT format object is created, we pass a configuration object with the splitCollection property set to true. By default, OpenLayers will wrap the WKT geometries into a geometry collection, but we'd prefer each point to be classified as an individual feature in the feature collection. This is really just minor semantics for our example.
The features are processed (format.readFeatures) and added to the vector source (this.addFeatures), this is the equivalent of vectorLayer.getSource() here.
$.ajax({
type: 'GET',
url: 'polygons.json',
context: this
}).done(function(data) {
var format = new ol.format.GeoJSON();
this.addFeatures(format.readFeatures(data));
});This request is the same as the previous request, although this time around, we fetch a file containing data in the GeoJSON format. The features are added to the same vector layer.
When using the loader function, we are responsible for loading and adding the features to the layer ourselves.