2017-09-20 2 views
0

Ich bin ein Auslöser Range bekommen: Maximale Call-Stack-Größe überschrittenrekursive neue Versprechen: Auslöser Range: Maximale Call-Stack-Größe überschritten

function getUser(userId) { 
    return new Promise((resolve, reject) => { 
     controller.storage.users.get(userId, function(err, user) { 
     if (err) reject(err); 

     if (user) { 
      if(!(user.orderData.pendingItem)) { 
      getUser(userId) 
      } 
      else { 
      resolve(user.orderData.pendingItem); 
      } 
     } 
     }) 
    }) 
    }; 

Das Dilemma ich habe, ist, dass, wenn ich controller.storage.users.get laufen muss es nicht immer lösen alle Eigenschaften und Werte des Benutzerobjekts sofort, weshalb ich versuche, es erneut auszuführen, wenn orderData.pendingItem nicht da ist.

Aber ich denke, weil es so oft ausgeführt wird, gibt es mir einen Call-Stack-Fehler.

Was ist der beste Weg, dieses Problem anzugehen oder dieses Problem zu lösen?

+1

Das sieht aus wie ein Telefon als Hammer verwendet wird. Sicher wäre die bessere Lösung, auf das zu warten, was 'user.orderData.pendingItem' setzt, um stattdessen zu beenden. Zumindest fügen Sie eine gewisse Verzögerung hinzu. –

+0

Selbst wenn Sie dies zum Funktionieren bringen, haben Sie im Wesentlichen ein 'while (true)' gemacht, aber rekursiv. Es wäre besser, 'pendingItem' zu einem Versprechen zu machen, wo immer es aufgefüllt wird, und dann können Sie es in Ihrem Code auflösen. Auf diese Weise erstellen Sie keinen Anruf-Stack, während dieser auf Vollständigkeit wartet. –

+0

@ug_ Ich stimme deinem Kommentar zu. Mein Problem ist im Moment, dass alle Daten im Speicher gespeichert werden, während 'user' oder' orderData' eigentlich in einer DB gespeichert werden sollten, damit ich stattdessen eine Versprechung auf die Abfrage setzen kann. Ich stehe jedoch ziemlich fest, bis ich die Genehmigung bekomme, mit einer DB fortzufahren. – user3593810

Antwort

2

Idealerweise sollten Sie für ein Ereignis, anstatt Polling zuhören, aber auf dem Verständnis, dass dies eine vorübergehende Lösung ist ...

new Promise() laufen Konstruktor synchron und es scheint, dass controller.storage.users.get() auch seinen Rückruf läuft synchron . Die Möglichkeit, dass die maximale Call-Stack-Größe überschritten wird, kann vermieden werden, indem der rekursive getUser()-Aufruf asynchron erzwungen wird und der einfachste Weg dazu ist, die Kette new Promise().then(/* recurse from here */) zu ketten.

function getUser(userId) { 
    return new Promise((resolve, reject) => { 
     controller.storage.users.get(userId, function(err, user) { 
      if (err) reject(err); 
      if (!user) reject(new Error('no user for id: ' + useId)); // this branch needs to be catered for 
      resolve(user); // make `user` available to the .then() below 
     }); 
    }).then(function(user) { 
     return (user.orderData && user.orderData.pendingItem) || getUser(userId); // compact and safe 
    }); 
} 

, die den Job tun sollten, aber ohne das „Maximum Call-Stack-Größe“ Schutz, die eine gute Chance, steht ein Prozessor oder zwei für keinen guten Grund zu braten.

Wie in den Kommentaren oben vorgeschlagen, können Sie und wahrscheinlich sollte eine gewisse Verzögerung in die Rekursion hinzufügen:

function delay(t) { 
    return new Promise(function(resolve) { 
     setTimeout(resolve, t); 
    }); 
} 

function getUser(userId) { 
    return new Promise((resolve, reject) => { 
     controller.storage.users.get(userId, function(err, user) { 
      if (err) reject(err); 
      if (!user) reject(new Error('no user for id: ' + useId)); // this branch needs to be catered for 
      resolve(user); // make `user` available to the .then() below 
     }); 
    }).then(function(user) { 
     return (user.orderData && user.orderData.pendingItem) || delay(200).then(function() { // adjust the delay to maximum acceptable value 
      return getUser(userId); 
     }); 
    }); 
} 
Verwandte Themen