heinetz: Javascript Fehler im Internet Explorer

Hallo Forum,

in einer komplexen Anwednung, die ich selbst nicht gebaut habe, kommt es im Internet Explorer 11 zu einem Fehler. Die Fehlermeldung lautet:

Das Objekt unterstützt die Eigenschaft oder Methode "finally" nicht

Der problematische Code sieht so aus:

ajax({
      url,
      method: 'post',
      headers: {
        'Content-Type': 'text/plain',
        Accept: 'application/json',
        // Csrf token that needs to be send with every request to craft
        'X-CSRF-Token': crsf
      },
      body: JSON.stringify(data)
    })
      .then(this.onSubmitSucess.bind(this))
      .catch(this.onSubmitError.bind(this))
      .finally(() => {
        this.elements.submitButton.classList.remove(
          'o-stock-subscription-form__submit-button--loading'
        );
      });

Ich denke, das kann man auch ohne finally() formulieren, aber ich bin mit JS-Promises nicht vertraut. Gefunden habe ich das hier:

https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Global_Objects/Promise/finally

Und es macht den Eindruck, die Methode finally() wäre leicht verzichtbar.

Kann ich den Code problemlos so umschreiben, dass er ohne finally() funktioniert?

danke für Tipps, heinetz

  1. Tach!

    Kann ich den Code problemlos so umschreiben, dass er ohne finally() funktioniert?

    Ein finally wird aufgerufen, egal ob Erfolg oder Misserfolg eintrat. Das heißt, wenn du den Code vom finally in beiden Fällen ausführst, ist das ein gleichwertiger Ersatz dafür.

          .then(this.onSubmitSucess.bind(this))
          .catch(this.onSubmitError.bind(this))
          .finally(() => {
            this.elements.submitButton.classList.remove(
              'o-stock-subscription-form__submit-button--loading'
            );
          });
    

    Du musst hier aber auch den Inhalt von then und catch umschreiben, denn da wird jetzt nur eine Funktionsreferenz übergeben, und da kannst du dich nicht so richtig dranhängen. Wenn ich mich jetzt nicht generell vertan habe, müsste das so laufen:

          .then(() => {
              this.onSubmitSucess();
              this.elements.submitButton.classList.remove(
                  'o-stock-subscription-form__submit-button--loading'
              );
          })
          .catch(() => {
              this.onSubmitError();
              this.elements.submitButton.classList.remove(
                  'o-stock-subscription-form__submit-button--loading'
              );
          });
    

    Das bind() fällt weg, das soll nur das aktuelle this reservieren, für die Zeit wenn der Callback erfolgt. Aber so eine Fat-Arrow-Funktionsdefinition () => {} reserviert das this nebenbei mit.

    dedlfix.

  2. Hallo,

    Kann ich den Code problemlos so umschreiben, dass er ohne finally() funktioniert?

    laut Doku sollte das gehen, aber das bringt nichts, da der IE then und catch auch nicht unterstützt.

    Wenn die Anwendung auch ohne Javascript läuft, vergiss den IE bzw. behandle ihn wie den Fall „kein JS“.

    Gruß
    Jürgen

    1. @@JürgenB

      Wenn die Anwendung auch ohne Javascript läuft, vergiss den IE bzw. behandle ihn wie den Fall „kein JS“.

      Es sollte heißen: Da die Anwendung auch ohne Javascript läuft … 😏

      LLAP 🖖

      --
      „Wer durch Wissen und Erfahrung der Klügere ist, der sollte nicht nachgeben. Und nicht aufgeben.“ —Kurt Weidemann
  3. Hallo heinetz,

    IE kann ohne Polyfill gar keine Promises. Hast du einen drin? Ist der unvollständig?

    Andererseits, das MDN Beispiel verwendet fetch, dein Code erinnert aber mehr an jQuery. Da gibt es then und catch, aber finally heißt dort always.

    Verzichtbar ist der finally Handler keinesfalls, ich nehme an dass er das UI reaktiviert.

    Des weiteren habe ich Bedenken wegen der Arrow-Funktion, das kann IE nicht. Verwendest du einen Precompiler?

    Viele Möglichkeiten, viele Fragen...

    Rolf

    --
    sumpsi - posui - clusi
    1. IE kann ohne Polyfill gar keine Promises. Hast du einen drin? Ist der unvollständig?

      Ohne die Details für finally nachgelesen zu haben fand ich das eine ganz nette Fingerübung. Hier mein ungetester Versuch:

      if (Promise instanceof Function && !Promise.prototype.finally instanceof Function) {
        Promise.prototype.finally = function (f) {
          this.then(_ => f())
          this.catch(_ => f())
          return this
        }
      }
      

      Für den Produktivbetrieb aber wahrscheinlich ungeeignet.

      1. Hallo 1unitedpower,

        Du kannst statt .then(f).catch(f) auch .then(f,f) aufrufen.

        Für einen einfachen Einsatz müsste deine Fassung ausreichen, aber zum Erfüllen des Spec-Draft (den ich nicht wirklich verstanden habe...) reicht es noch nicht.

        Auf Github gibt's einen ausführlicheren Polyfill. Aber der scheint sich seiner selbst auch nicht sicher zu sein, weil er ein natives finally nicht beibehalten mag.

        Unnötig ist er auf keinen Fall, weil die finally-Methode immer noch im Draft-State und noch gar nicht so lange in den Browsern drin ist (in Node.js und im öffentlichen Edge noch gar nicht).

        Rolf

        --
        sumpsi - posui - clusi