AngularJS - Mischen von HTTP und benutzerdefinierten Versprechungen mit Rekursion

Oct 23 2020

Ich habe einen Funktions-Wrapper geschrieben, der zwischengespeicherte Werte für HTTP-Antworten zurückgibt. In einer bestimmten Situation (gekennzeichnet durch einen Kommentar // <--HERE) sehe ich inkonsistentes Verhalten. Ich bin mir ehrlich gesagt nicht sicher, was genau die Inkonsistenz ist, aber unter dem Strich wartet der Cache nach Ablauf (has_expired) nicht darauf, dass der http get im rekursiven Aufruf zurückkehrt.

Ich vermute, ich habe nicht irgendwo eine "Rückkehr" zu einem Versprechen gemacht, aber ich kann nicht herausfinden, wo (und warum). Muss ich eine Rückgabe vor localForage.removeItem(und wenn ja, warum?)

function cache_or_http(url,key) {

    if (dont_use_cache()) {
      return $http.get(url); } var d = $q.defer();
    localforage.getItem(key)
    .then (function(data) {
         if (data) { // exists
            if (has_expired(data.created_at)) {
                localforage.removeItem(key)
                .then (function() {return cache_or_http(url,key);}) // <--HERE
                .catch(function() {return do_error_handling();})
            } else { // not expired
                 d.resolve(JSON.parse(data.value));
                 return d.promise;
             }
         } else {
            // doesn't exist
            return $http.get(url)
            .then (function(data) {
                cache_entry = {
                    'value': JSON.stringify(data),
                    'created_at': moment().toString()
                };
                localforage.setItem(key, cache_entry);
                d.resolve(data);
                return (d.promise);
            });
         } // doesn't exist
    }); // getItem .then
    return (d.promise);
 }

Antworten

1 georgeawg Oct 23 2020 at 08:38

Es besteht keine Notwendigkeit, ein neues Versprechen mit herzustellen $q.defer. Die .thenMethode eines Versprechens gibt bereits ein Versprechen zurück.

function cache_or_http(url,key) {
    ̶v̶a̶r̶ ̶d̶ ̶=̶ ̶$̶q̶.̶d̶e̶f̶e̶r̶(̶)̶;̶
    ̲r̲e̲t̲u̲r̲n̲ localforage.getItem(key)
    .then (function(data) {
         if (data) { // exists
            if (has_expired(data.created_at)) {
                ̲r̲e̲t̲u̲r̲n̲ localforage.removeItem(key)
                .then (function() {return cache_or_http(url,key);}) // <--HERE
                .catch(function() {return do_error_handling();})
            } else { // not expired
                 ̶d̶.̶r̶e̶s̶o̶l̶v̶e̶(̶J̶S̶O̶N̶.̶p̶a̶r̶s̶e̶(̶d̶a̶t̶a̶.̶v̶a̶l̶u̶e̶)̶)̶;̶ 
                 return JSON.parse(data.value);
            }
         } else {
            // doesn't exist
            return $http.get(url)
            .then (function(data) {
                cache_entry = {
                    'value': JSON.stringify(data),
                    'created_at': moment().toString()
                };
                ̲r̲e̲t̲u̲r̲n̲ localforage.setItem(key, cache_entry);
                ̶d̶.̶r̶e̶s̶o̶l̶v̶e̶(̶d̶a̶t̶a̶)̶;̶
                ̶r̶e̶t̶u̶r̶n̶ ̶(̶d̶.̶p̶r̶o̶m̶i̶s̶e̶)̶;̶
            });
         } // doesn't exist
    }); // getItem .then
    ̶r̶e̶t̶u̶r̶n̶ ̶(̶d̶.̶p̶r̶o̶m̶i̶s̶e̶)̶;̶
 }

Weitere Informationen finden Sie unter

  • Ist das ein "Deferred Antipattern"?