Add Zotero.Sync.APIClient.getPaginatedResults()

Function that automatically follows Link headers and makes additional
requests as necessary, feeding the XMLHTTPRequest object from each
request to a reducer function.
This commit is contained in:
Dan Stillman 2017-02-24 18:39:23 -05:00
parent 57626101ac
commit a9dda10a7d

View file

@ -661,6 +661,77 @@ Zotero.Sync.APIClient.prototype = {
}),
/**
* Retrieve paginated requests automatically based on the Link header, passing the results to a
* reducer
*
* @param {String} initialURL
* @param {Function} reducer - Reducer function taking (previousValue, xmlhttp, restart)
* accumulator: Return value from previous invocation, or initialValue
* xmlhttp: XMLHTTPRequest object from previous request
* restart: A function to restart from the beginning
* @param {mixed} initialValue
* @return {mixed} - The reduced value
*/
getPaginatedResults: Zotero.Promise.coroutine(function* (initialURL, reducer, initialValue) {
let url = initialURL;
let accumulator;
let restart = false;
while (true) {
let xmlhttp = yield this.makeRequest("GET", url);
accumulator = reducer(
accumulator === undefined ? initialValue : accumulator,
xmlhttp,
function () {
restart = true;
}
);
if (restart) {
accumulator = undefined;
url = initialURL;
restart = false;
continue;
}
let link = this._parseLinkHeader(xmlhttp.getResponseHeader('Link'));
if (link && link.next) {
url = link.next;
}
else {
break;
}
}
return accumulator;
}),
/**
* Parse a Link header
*
* From https://gist.github.com/deiu/9335803
* MIT-licensed
*/
_parseLinkHeader: function (link) {
var linkexp = /<[^>]*>\s*(\s*;\s*[^\(\)<>@,;:"\/\[\]\?={} \t]+=(([^\(\)<>@,;:"\/\[\]\?={} \t]+)|("[^"]*")))*(,|$)/g;
var paramexp = /[^\(\)<>@,;:"\/\[\]\?={} \t]+=(([^\(\)<>@,;:"\/\[\]\?={} \t]+)|("[^"]*"))/g;
var matches = link.match(linkexp);
var rels = {};
for (var i = 0; i < matches.length; i++) {
var split = matches[i].split('>');
var href = split[0].substring(1);
var ps = split[1];
var s = ps.match(paramexp);
for (var j = 0; j < s.length; j++) {
var p = s[j];
var paramsplit = p.split('=');
var name = paramsplit[0];
var rel = paramsplit[1].replace(/["']/g, '');
rels[rel] = href;
}
}
return rels;
},
_parseJSON: function (json) {
try {
json = JSON.parse(json);