2017-08-08 1 views
2

Ich habe begonnen, mit Promises zu betrachten und habe damit begonnen, eine einfache Funktion zusammenzustellen und es ein paar Mal aufrufen. Ich brauche eine Plausibilitätsprüfung um abzulehnen und zu lösen.Wie richtig zu verwenden und für Versprechen Verweigern

  1. Ist dies der richtige Weg, um eine Funktion "Promistifizieren"?
  2. Ist dies der richtige Weg, um mit Ablehnung und Auflösung umzugehen?
  3. Alles, was ich falsch verstanden habe?

    const Redis  = require('ioredis'); 
    const redis  = new Redis({ 
        port: 6379, 
        host: '127.0.0.1' 
    }); 
    
    
    function checkValues(name, section) { 
        return new Promise((resolve, reject) => { 
         redis.multi() 
         .sismember('names', name) 
         .sismember('sections', section) 
         .exec() 
         .then((results) => { 
          if(results[0][1] === 1 && results [1][1] ===1) { 
           reject('Match on both.'); 
          } else if(results[0][1] === 1 || results [1][1] ===1) { 
           reject('Match on one.'); 
          } else { 
           redis.multi() 
           .sadd('names', name) 
           .sadd('sections', section) 
           .exec() 
           .then((results) => { 
            // Lazy assumption of success. 
            resolve('Added as no matches.'); 
           }) 
           // No catch needed as this would be thrown up and caught? 
          } 
         }) 
         .catch((error) => { 
          console.log(error); 
         }); 
        }); 
    } 
    
    
    // Call stuff. 
    checkValues('barry', 'green') 
    .then((result) => { 
        // Added as no matches "resolve" message from 'barry', 'green' 
        console.log(result); 
        retutn checkValues('steve', 'blue'); 
    }) 
    .then((result) => { 
        // Added as no matches "resolve" message from 'steve', 'blue' 
        retutn checkValues('steve', 'blue'); 
    }) 
    .then((result) => { 
        // Match on both "reject" message from 'steve', 'blue' 
        console.log(result); 
    }) 
    .catch((error) => { 
        console.log(error); 
    }); 
    

Antwort

1

Mehr Punkte:

  1. Sie das nicht verwenden explicit-promise-construction-antipattern
  2. Als allgemeine Regel in dem anti-Muster Spülen nach dem new Promise() Wrapper zu entfernen, ändern resolve Aussagen zu return und reject Aussagen zu throw new Error(...).
  3. .catch() Fänge! Wenn Fehler vom Aufrufer beobachtbar/handhabbar sein sollen, dann fangen Sie entweder nicht in checkValues() ein oder fangen und werfen erneut. Das Abfangen ohne erneutes Werfen führt dazu, dass sich das zurückgegebene Versprechen auf seinem Erfolgspfad einnistet, niemals auf seinem Fehlerpfad, der für die Fehlerkorrektur groß ist, aber nicht immer angemessen ist.
  4. Schlagen Sie vor, dass alle drei Fälle, "Übereinstimmungen bei beiden", "Übereinstimmungen bei Eins" und "Als keine Übereinstimmungen hinzugefügt", wirklich erfolgreich sind. Wenn es keinen bestimmten Grund dafür gibt, dass "Match auf beiden" und "Match auf Eins" als Fehlerbedingungen angesehen werden sollen, dann return anstatt reject/throw. Auf diese Weise wird Ihr Anruf stuff Kette seinen Erfolgsweg, .then().then().then(), ungeachtet des erwarteten Ergebnisses fortschreiten; Nur ein unerwarteter Fehler wird den Fehlerpfad durchlaufen, um von der endgültigen .catch() abgefangen zu werden. Dies ist keine allgemeine Regel; sehr oft ist Werfen das Richtige, aber nicht hier.
function checkValues(name, section) { 
    return redis.multi() 
    .sismember('names', name) 
    .sismember('sections', section) 
    .exec() 
    .then((results) => { 
     if(results[0][1] === 1 && results [1][1] === 1) { 
      return 'Match on both.'; 
     } else if(results[0][1] === 1 || results [1][1] ===1) { 
      return 'Match on one.'; 
     } else { 
      return redis.multi() 
      .sadd('names', name) 
      .sadd('sections', section) 
      .exec() 
      .then((results) => { 
       return 'Added as no matches.'; 
      }); 
     } 
    }) 
    .catch((error) => { 
     console.log(error); 
     throw error; 
    }); 
} 

// Call stuff. 
checkValues('barry', 'green') 
.then((result) => { 
    console.log(result); // expect 'Added as no matches' 
    return checkValues('steve', 'blue'); 
}) 
.then((result) => { 
    return checkValues('steve', 'blue'); // expect 'Added as no matches' 
}) 
.then((result) => { 
    console.log(result); // expect 'Match on both' 
}) 
.catch((error) => { 
    // only an unexpected error will land here 
    console.log(error); 
}); 
+0

Danke für die ausführliche Antwort. Wenn ich zurückkomme, kann ich mehrere Werte zurückgeben: {success: 'false', Nachricht: 'single match'}. Oder gibt es einen besseren/standardisierten Weg, dies zu erreichen? –

+1

Ja, das ist genau der Weg, um mehrere Werte zurückzugeben. In der Tat ist es der einzige Weg. (OK, Sie können auch ein konstruiertes Objekt anstelle eines einfachen Objekts zurückgeben, aber das ist im Wesentlichen das Gleiche). –

3

Nein, ist diese Art eines anti-Muster. Sie haben bereits eine Funktion, die ein Versprechen zurückgibt, sodass Sie sie nicht in ein anderes Versprechen einbinden müssen. Sie können es einfach zurückgeben. Denken Sie daran, dass then() eine Zusage zurückgibt, die auf den Rückgabewert then aufgelöst wird. Sie können auch ein anderes Versprechen von then zurückgeben. Normalerweise sieht das sehr sauber aus, aber in diesem Fall brauchen Sie etwas Logik in der then Funktion, so dass es ein wenig unordentlich wird.

function checkValues(name, section) { 
    // Just return this Promise 
    return redis.multi() 
    .sismember('names', name) 
    .sismember('sections', section) 
    .exec() 
    .then((results) => { 
     if(results[0][1] === 1 && results [1][1] ===1) { 
      // Rejections will be caught down the line 
      return Promise.reject('Match on both.'); 
     } else if(results[0][1] === 1 || results [1][1] ===1) { 
      return Promise.reject('Match on one.'); 
     } else { 
      // You can return another Promise from then() 
      return redis.multi() 
      .sadd('names', name) 
      .sadd('sections', section) 
      .exec() 
     } 
    }) 
// You don't need to catch here - you can catch everything at the end of the chain 
} 
Verwandte Themen