@knu2xs wrote:
In this case I have zero control over the REST endpoint for retrieving data. Hence, I am taking a stab at creating an adaptor. The challenge arises with the
findAll
method, since the maximum number of features exceeds the maximum number of features the REST endpoint will return. However, the REST endpoint does support pagnation. As a result, I am trying to sort out how to navigate the world of promises to get all the records returned…and apparently not doing a very good job. Here is the code I have thus far. Thank you in advance for any assistance or insight you may be able to provide../app/adapters/reach.js
import DS from 'ember-data';` import request from '../utils/request'; import ENV from '../config/environment'; import Ember from 'ember'; const urlFeatureLayer = ENV.APP.ARCGIS.POINTS.URL; const urlQuery = `${urlFeatureLayer}/query`; const uidField = 'reachId'; // not the same one ArcGIS uses // for quickly making a get request to the ArcGIS REST endpoint const makeQueryRequest = (opts) => { opts.f = 'json'; // just ensuring this is taken care of // providing a default if none is provided if (!opts.where){ opts.where = '1=1'; } // using Ember's built in jQuery to parameterize inputs for request opts = Ember.$.param(opts); // combine params onto url, and make request let url = `${urlQuery}?${opts}`; return request(url, {method: 'GET'}); } // pulling together the steps to side step the maximum record response limit let retrieveAll = () => { // retrieve the maximum feature count request(`${urlFeatureLayer}?f=json`, {method: 'GET'}) .then((respProp) => { Ember.debug(`Max Record Count: ${respProp.maxRecordCount}`); // get the feature count makeQueryRequest({returnCountOnly: true}) .then((respCnt) => { Ember.debug(`Feature Count: ${respCnt.count}`); // calculate the number of pulls required to get all the data let pullCount = Math.ceil(respCnt.count / respProp.maxRecordCount); Ember.debug(`Pull Count: ${pullCount}`); // iteratively, in chunks, retrieve all the features let allFeatures = []; for (let i = 0; i < pullCount; i++){ let offset = i * respProp.maxRecordCount; let recordCount = respProp.maxRecordCount; allFeatures.push(makeQueryRequest({ resultOffset: offset, resultRecordCount: recordCount })); } // catcher to get all the promises and send back the results Promise.all(allFeatures).then((allFeatures) => { return allFeatures; }); }); }); } export default DS.JSONAPIAdapter.extend({ findAll: function(store) { return retrieveAll(); // let opts = Ember.$.param({ // where: '1=1', // f: 'json', // outFields: '*' // }); // let url = `${urlQuery}?${opts}`; // return request(url, {method: 'GET'}); }, findRecord (store, type, id) { let opts = Ember.$.param({ where: `${uidField} = ${id}`, f: 'json', outFields: '*' }); let url = `${urlQuery}?${opts}`; return request(url, {method: 'GET'}); } });
The referenced
request
is really little more than a wrapper for fetch, but here it is for reference…./utils/request.js import Ember from 'ember'; import fetch from 'fetch'; import addToken from './add-token'; import encodeForm from './encode-form'; /** * Fetch based request method */ export default function request (url, opts = {}) { // if we are POSTing, we need to manually set the content-type because AGO // actually does care about this header if (opts.method && opts.method === 'POST') { if (!opts.headers) { opts.headers = { 'Accept': 'application/json, application/xml, multipart/form-data, text/plain, text/html, *.*', 'Content-Type': 'multipart/form-data' }; } // if we have a data, prep it to send if (opts.data) { opts.body = encodeForm(opts.data); } } opts.redirect = 'follow'; opts.mode = 'cors'; // add a token if provided url = addToken(url, opts.token); Ember.debug('Making request to ' + url); return fetch(url, opts).then(checkStatusAndParseJson); } /** * Fetch does not reject on non-200 responses, so we need to check this manually */ function checkStatusAndParseJson (response) { let error; Ember.debug('Fetch request status: ' + response.status); // check if this is one of those groovy 200-but-a-400 things if (response.status >= 200 && response.status < 300) { return response.json().then(json => { // cook an error if (json.error) { error = new Error(json.error.message); error.code = json.error.code || 404; error.response = response; Ember.debug('Error in response: ' + json.error.message); throw error; } else { return json; } }); } else { // Response has non 200 http code error = new Error(response.statusText); error.response = response; throw error; } }
Posts: 2
Participants: 2