function _fetchData()

in packages/miew/src/Miew.js [1857:1934]


function _fetchData(source, opts, job) {
  return new Promise(((resolve) => {
    if (job.shouldCancel()) {
      throw new Error('Operation cancelled');
    }
    job.notify({ type: 'fetching' });

    // allow for source shortcuts
    source = resolveSourceShortcut(source, opts);

    // detect a proper loader
    const TheLoader = _.head(io.loaders.find({ type: opts.sourceType, source }));
    if (!TheLoader) {
      throw new Error(LOADER_NOT_FOUND);
    }

    // split file name
    const fileName = opts.fileName || TheLoader.extractName(source);
    if (fileName) {
      const [name, fileExt] = utils.splitFileName(fileName);
      _.defaults(opts, { name, fileExt, fileName });
    }

    // should it be text or binary?
    updateBinaryMode(opts);

    // FIXME: All new settings retrieved from server are applied after the loading is complete. However, we need some
    // flags to alter the loading process itself. Here we apply them in advance. Dirty hack. Kill the server, remove
    // all hacks and everybody's happy.
    let newOptions = _.get(opts, 'preset.expression');
    if (!_.isUndefined(newOptions)) {
      newOptions = JSON.parse(newOptions);
      if (newOptions && newOptions.settings) {
        const keys = ['singleUnit'];
        for (let keyIndex = 0, keyCount = keys.length; keyIndex < keyCount; ++keyIndex) {
          const key = keys[keyIndex];
          const value = _.get(newOptions.settings, key);
          if (!_.isUndefined(value)) {
            settings.set(key, value);
          }
        }
      }
    }

    // create a loader
    const loader = new TheLoader(source, opts);
    loader.context = opts.context;
    job.addEventListener('cancel', () => loader.abort());

    loader.addEventListener('progress', (event) => {
      if (event.lengthComputable && event.total > 0) {
        reportProgress(loader.logger, 'Fetching', event.loaded / event.total);
      } else {
        reportProgress(loader.logger, 'Fetching');
      }
    });

    console.time('fetch');
    const promise = loader.load()
      .then((data) => {
        console.timeEnd('fetch');
        opts.context.logger.info('Fetching finished');
        job.notify({ type: 'fetchingDone', data });
        return data;
      })
      .catch((error) => {
        console.timeEnd('fetch');
        opts.context.logger.debug(error.message);
        if (error.stack) {
          opts.context.logger.debug(error.stack);
        }
        opts.context.logger.error('Fetching failed');
        job.notify({ type: 'fetchingDone', error });
        throw error;
      });
    resolve(promise);
  }));
}