Как добавить polyfill для поддержки finally () в Edge? - PullRequest
0 голосов
/ 15 ноября 2018

Я использую библиотеку axios и использую then (), catch () и finally ().Отлично работает в Chrome.Однако метод finally () не работает в MS Edge.Я исследовал, используя polyfills или прокладки, и я потерян.Я не использую webpack или транспарант и не планирую добавлять их.Мне нужно, чтобы все было просто.Как я могу добавить polyfill, чтобы убедиться, что finally () работает в Edge?Спасибо!

1 Ответ

0 голосов
/ 15 ноября 2018

Это было немного сложнее, чем я думал. Это должно даже обрабатывать распространение таблицы 100 * *species в дополнение к поведению, описанному ниже:

Promise.prototype.finally = Promise.prototype.finally || {
  finally (fn) {
    const onFinally = cb => Promise.resolve(fn()).then(cb);
    return this.then(
      result => onFinally(() => result),
      reason => onFinally(() => Promise.reject(reason))
    );
  }
}.finally;

Эта реализация основана на документированном поведении finally() и зависит от того, * then() соответствует спецификации:

  • A finally обратный вызов не получит никакого аргумента, поскольку нет надежных средств определения того, было ли обещание выполнено или отклонено. Этот вариант использования предназначен именно для случаев, когда вас не заботит причина отклонения или значение выполнения, и поэтому нет необходимости указывать его.

  • В отличие от Promise.resolve(2).then(() => {}, () => {}) (который будет разрешен с undefined), Promise.resolve(2).finally(() => {}) будет разрешен с 2.

  • Аналогично, в отличие от Promise.reject(3).then(() => {}, () => {}) (который будет выполнен с undefined), Promise.reject(3).finally(() => {}) будет отклонено с 3.

Примечание: A throw (или возврат отклоненного обещания) в обратном вызове finally отклонит новое обещание с причиной отказа, указанной при вызове throw().

И, конечно, демонстрация эквивалентного поведения:

const logger = (label, start = Date.now()) => (...values) =>
  console.log(label, ...values, `after ${Date.now() - start}ms`);
const delay = (value, ms) => new Promise(resolve => setTimeout(resolve, ms, value));

test('native');

// force Promise to use the polyfill implementation
Promise.prototype.finally = /* Promise.prototype.finally || */ {
  finally (fn) {
    const onFinally = cb => Promise.resolve(fn()).then(cb);
    return this.then(
      result => onFinally(() => result),
      reason => onFinally(() => Promise.reject(reason))
    );
  }
}.finally;

test('polyfill');

function test (impl) {
  const log = ordinal => state => logger(`${ordinal} ${impl} ${state}`);
  const first = log('first');

  delay(2, 1000)
    .finally(first('settled'))
    .then(first('fulfilled'), first('rejected'));

  const second = log('second');

  delay(Promise.reject(3), 2000)
    .finally(second('settled'))
    .then(second('fulfilled'), second('rejected'));

  const third = log('third');

  delay(4, 3000)
    .finally(third('settled'))
    .finally(() => delay(6, 500))
    .then(third('fulfilled'), third('rejected'));

  const fourth = log('fourth');

  delay(5, 4000)
    .finally(fourth('settled'))
    .finally(() => delay(Promise.reject(7), 500))
    .then(fourth('fulfilled'), fourth('rejected'));
}
.as-console-wrapper{max-height:100%!important}

Спасибо @ Bergi за его вклад в этот ответ. Пожалуйста, ознакомьтесь с его реализацией и добавьте комментарий, если вы нашли этот пост полезным.

...