ArcGIS Maps SDK for JavaScript

Rest is up to the task

At version 4.20 of the ArcGIS API for JavaScript, we deprecated Tasks in favor of using more modular classes and objects found inside the esri/rest folder. At version 4.24 (summer release) of the ArcGIS API for JavaScript, we will be removing support for Tasks.

"esri/rest" folder
"esri/rest" folder

These changes are already available for our users to test using next via CDN and NPM: https://github.com/Esri/feedback-js-api-next

Why did we do this? This will make it easier to incorporate your code into a more modular app design, and also reduce unnecessary dependencies (you only import what you want). The new rest modules are functions, which do not require constructors, so you can use their methods immediately.

Also, because of the more modular design, you can import just one or more methods of a rest module, instead of having to import the whole module. There is one caveat to that statement though, and we’ll discuss that after we see some code examples.

Now, let’s look at a couple of examples. First, this is how we used to handle querying using Tasks:

// example of using deprecated QueryTask
require([
  "esri/tasks/QueryTask", "esri/tasks/support/Query", ...
], function(QueryTask, Query, ...){

  // URL to the layer of interest to query
  let queryUrl = "https://sampleserver6.arcgisonline.com/arcgis/rest/services/Census/MapServer/3";

  // create a new QueryTask with URL from above
  let queryTask = new QueryTask({
    url: queryUrl
  });

  // create the Query object
  let queryObject = new Query();
  queryObject.where = "STATE_NAME = 'Washington'";
  queryObject.outSpatialReference = { wkid:4269 };
  queryObject.returnGeometry = true;
  queryObject.outFields = [ "HOUSEHOLDS" ];

  // when resolved, returns features and graphics that satisfy the query
  queryTask.execute(queryObject).then(function(results){
    console.log(results.features);
  });
});

This is the same example as above, but using esri/rest/query:

// same example, but using "esri/rest/query"
require([
  "esri/rest/query", "esri/rest/support/Query", ...
], function(query, Query, ... ) {

  // URL to the layer of interest to query
  let queryUrl = "https://sampleserver6.arcgisonline.com/arcgis/rest/services/Census/MapServer/3";

  // create the Query object
  let queryObject = new Query();
  queryObject.where = "STATE_NAME = 'Washington'";
  queryObject.outSpatialReference = { wkid:4269 };
  queryObject.returnGeometry = true;
  queryObject.outFields = [ "HOUSEHOLDS" ];

  // when resolved, returns features and graphics that satisfy the query
  query.executeQueryJSON(queryUrl, queryObject).then(function(results){
    console.log(results.features);
  });
});

Notice that the code looks super similar? In this case (and in almost every case, actually) migrating from Tasks to rest is simple and straightforward and, thankfully, well documented. Here, we had to rename the modules in the require statement, and move the URL from the QueryTask constructor into the executeQueryJSON() method parameter.

And here we have the same example as above, but we can also use @arcgis/core ES modules to import @arcgis/core/rest/query/executeQueryJSON so we don’t have to waste resources with loading the rest of the esri/rest/query methods:

// same example, but only load the query method of interest with ES Modules
import { executeQueryJSON } from "@arcgis/core/rest/query";
import Query from "@arcgis/core/rest/support/Query";

// URL to the layer of interest to query
let queryUrl =
  "https://sampleserver6.arcgisonline.com/arcgis/rest/services/Census/MapServer/3";

// create the Query object
let queryObject = new Query({
    where: "STATE_NAME = 'Washington'",
    outSpatialReference: { wkid: 4269 },
    returnGeometry: true,
    outFields: ["HOUSEHOLDS"]
});

// when resolved, returns features and graphics that satisfy the query
executeQueryJSON(queryUrl, queryObject).then((results) => {
  console.log(results.features);
});

Notice that the code also looks super similar? The main difference is that when tree-shaking is enabled in your build tools, the app avoids loading the other 6 querying methods, which reduces load time and the resources consumed.

It should also be noted, that rather than using the query modules directly, you should probably be using the query methods on the Layer. This would include methods like queryFeatures, queryRelatedFeatures, and more. These query methods will take into account the capabilities of the backing service so you don’t have to.

One last thing to note about this change is that we also deprecated the Portal helper methods at version 4.21, and are removing these five Task-based functions at 4.24 as well:

We recommend using the URLs from the Portal.helperServices with their respective rest modules instead. Let’s look at an example using esri/rest/print with helperServices.

// example using "esri/rest/print" with helperServices
require([
 "esri/portal/Portal",
 "esri/rest/print",
 "esri/rest/support/PrintTemplate",
 "esri/rest/support/PrintParameters",
 ...
], function(Portal, print, PrintTemplate, PrintParameters, ... ) {

  // create new Portal object with relevant URL
  const portal = new Portal({
     url: "YOUR_PORTAL_URL"
  });

  const template = new PrintTemplate({
    format: "pdf",
    exportOptions: {
      dpi: 12
    },
    layout: "a4-portrait",
    layoutOptions: {
      titleText: "Gillette Stadium",
      authorText: "Thomas B."
    }
  });

  const params = new PrintParameters({
    view: view,
    template: template
  });

  // load Portal instance
  portal.load().then(function() {
    // display URLs to all helper services
    console.log("Show helperServices URLs: ", portal.helperServices);
    // access helperServices from the Portal instance
    // to get the print URL of interest
    const printURL = portal.helperServices.printTask.url;
    // use helperServices to perform printing
    print.execute(printURL, params).then(printResult).catch(printError);
  }

  function printResult(result) {
    console.log(result.url);
    window.open(result.url);
  }

  function printError(err) {
    console.log("Something broke: ", err);
  }
});

We can see from the above code snippet that once we get the helperServices URLs, using print is straightforward. If we were unsure as to what service URLs are available from the portal, displaying the helperServices to the console is an easy way to see what options are available.

Lastly, if you need more convincing, here’s a great video from René that will really help you out:
Migrate off Tasks in the ArcGIS API for JavaScript TODAY!

TL;DR

The best time to update from Tasks to rest was 3 releases ago. The second best time, is now.

About the authors

Passionate about JavaScript, maps, and writing (not necessarily in that order). Big fan of squirrels. Journeyman mapper of Utility Lines and Public Restrooms. Product Engineer on the ArcGIS API for JavaScript team. In Noah’s spare time, he also enjoys parenting.

Connect:

SoftWhere Developer, blogger, author, geodev, and connoisseur of programming languages and JavaScript frameworks. I blog at https://odoe.net and post videos at https://www.youtube.com/c/renerubalcava I write code, sometimes it even works.

Connect:
Subscribe
Notify of
0 Comments
Inline Feedbacks
View all comments

Next Article

Harnessing the Power of Imagery: A Programmatic Approach

Read this article