2016-07-29 17 views
0

Ich habe den folgenden Code in Knoten v6.3.0 läuft auf einem API, das zwei separate Versprechungen abhängig von einer Bedingung, ob ein Param existiert in der POST-Anfrage läuft.DRY up Versprechen in Javascript

if (paramExists) { 
    // call database with this query 
    User.filter(/* do something with param */) 
     .then(function (user) { 
      Data.filter(/* same in both conditions */) 
       .then(function (data) { 
        // join data and user 
        res.send(joinedData); 
       }) // omit catch for clarity 
     }) // omit catch for clarity 
} else { 
    // call database with this query 
    User.filter(/* do something with header */) 
     .then(function (user) { 
      Data.filter(/* same in both conditions */) 
       .then(function (data) { 
        // join data and user 
        res.send(joinedData); 
       }) // omit catch for clarity 
     }) // omit catch for clarity 
} 

Ich bin sicher, dass es eine Möglichkeit, diesen Code zu vertrocknen ist, so dass das erste Versprechen in beiden Bedingungen die Benutzer auf das zweite Versprechen geht, aber ich kann nicht herausfinden, wie. Soll ich einen Generator benutzen oder gibt es eine Möglichkeit, dies mit Versprechen zu tun, die ich nicht bekomme?

+0

Haben Sie "Promise.all" in Betracht gezogen? Am Ende sieht es so aus: var p1 = Benutzer.filter (paramExists? Args1: args2), p2 = Data.filter (...); Promise.all ([p1, p2]). Dann (function (user, data) {...}); ' – numbers1311407

+0

Klingt so, als würdest du nach [Bedingungen in Versprechensketten] fragen (http://stackoverflow.com/ q/26599798/1048572)? – Bergi

Antwort

2

Da der einzige Teil, der zwischen den beiden Zweigen, anders zu sein scheint, ist, was Sie User.filter() passieren, Sie diesen Wert in eine lokale Variable setzen kann in einer Bedingung und dann eine Version des Codes mit der Variable ausführen.

Sie können auch zu Ihrer gekettet Methoden vereinfachen unnötige Verschachtelung zu entfernen:

var arg; 
if (paramExists) { 
    arg = ...  // some logic 
} else { 
    arg = ...  // some different logic 
} 
// call database with this query 
User.filter(arg).then(function (user) { 
    return Data.filter(...); 
}).then(function (data) { 
    // join data and user 
    res.send(joinedData); 
}); // omit catch for clarity 

Sie auch ein ternäres verwenden:

var arg = paramExists ? someLogic : someOtherLogic; 
// call database with this query 
User.filter(arg).then(function (user) { 
    return Data.filter(...); 
}).then(function (data) { 
    // join data and user 
    res.send(joinedData); 
}); // omit catch for clarity 

Wenn Sie sowohl user und data zugreifen müssen zum Senden der Antwort (ein wenig schwer in Ihrem Pseudocode zu sagen), dann könnten Sie Ihre Verschachtelung behalten:

var arg = paramExists ? someLogic : someOtherLogic; 
// call database with this query 
User.filter(arg).then(function (user) { 
    return Data.filter(...).then(function(data) { 
     // join data and user 
     res.send(joinedData); 
    }); 
}); // omit catch for clarity 
+0

Ich denke, dies könnte ein Problem sein, weil das OP das Ergebnis des ersten Versprechens mit dem zweiten verbinden muss, und mit dem verketteten Callback-Ansatz sind die zurückgegebenen Benutzerdaten außerhalb des Geltungsbereichs. – numbers1311407

+0

@ numbers1311407 - Ich habe diese Option wieder hinzugefügt. Schwer zu sagen, diese Detailstufe im Pseudocode manchmal. Oder sie können Daten auch auf derselben Ebene mit einem dieser [Schemata] teilen (http://stackoverflow.com/questions/28714298/how-to-chain-and-share-prior-results-with- promises/28714863 # 28714863). – jfriend00

+0

Eigentlich ja, die zweite Option funktioniert. Danke dafür, zu lernen, Versprechungen zu lieben. – alexi2

2

Sie können etwas wie folgt tun. Ich nehme an, dass Data.filter ein Versprechen auch zurückgibt.

if (paramExists) { 
    // call database with this query 
    User.filter(/* do something with param */) 
     .then(sameCondition); // omit catch for clarity 
} else { 
    // call database with this query 
    User.filter(/* do something with header */) 
     .then(sameCondition); // omit catch for clarity 
} 

function sameCondition(user) { 
    return Data.filter(/* same in both conditions */) 
    .then(function (data) { 
     // join data and user 
     res.send(joinedData); 
    }); // omit catch for clarity 
} 
+0

Sie können einfacher gehen und nur verschiedene Params zum ersten Versprechen basierend auf der Bedingung übergeben, z. 'User.filter (paramExists? Args1: args2) .dann (restOfBehavior);' – numbers1311407

+0

Sieht einfach genug aus, lass es mich versuchen. – alexi2

1

etwas tun ...

var task1 = paramExists ? 
    User.filter(/* do something with param */) : 
    User.filter(/* do something with header */) 

var doFilter = task1.then(function() { 
    return Data.filter(/* same in both conditions */) 
}) 

doFilter.then(function (joinedData) { 
    res.send(joinedData); 
});