Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Fix problem with calling the browser version concurrently #53

Merged
merged 11 commits into from
Dec 7, 2020
64 changes: 46 additions & 18 deletions browser.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,17 @@
'use strict';
const isIp = require('is-ip');

class CancelError extends Error {
constructor() {
super('Request was cancelled');
this.name = 'CancelError';
}

get isCanceled() {
return true;
}
}

const defaults = {
timeout: 5000
};
Expand All @@ -16,11 +27,12 @@ const urls = {
]
};

let xhr;
const sendXhr = (url, options, version) => {
const xhr = new XMLHttpRequest();

const sendXhr = async (url, options, version) => {
return new Promise((resolve, reject) => {
xhr = new XMLHttpRequest();
let _reject;
const promise = new Promise((resolve, reject) => {
_reject = reject;
xhr.addEventListener('error', reject, {once: true});
xhr.addEventListener('timeout', reject, {once: true});

Expand All @@ -39,24 +51,40 @@ const sendXhr = async (url, options, version) => {
xhr.timeout = options.timeout;
xhr.send();
});
};

const queryHttps = async (version, options) => {
let ip;
const urls_ = [].concat.apply(urls[version], options.fallbackUrls || []);
for (const url of urls_) {
try {
// eslint-disable-next-line no-await-in-loop
ip = await sendXhr(url, options, version);
return ip;
} catch (_) {}
}
promise.cancel = () => {
xhr.abort();
_reject(new CancelError());
};

throw new Error('Couldn\'t find your IP');
return promise;
};

queryHttps.cancel = () => {
xhr.abort();
const queryHttps = (version, options) => {
let request;
const promise = (async function () {
const urls_ = [].concat.apply(urls[version], options.fallbackUrls || []);
for (const url of urls_) {
try {
request = sendXhr(url, options, version);
// eslint-disable-next-line no-await-in-loop
const ip = await request;
return ip;
} catch (error) {
if (error instanceof CancelError) {
throw error;
}
}
}

throw new Error('Couldn\'t find your IP');
})();

promise.cancel = () => {
request.cancel();
};

return promise;
};

module.exports.v4 = options => queryHttps('v4', {...defaults, ...options});
Expand Down