2016-11-08 3 views
0

Ich möchte versuchen, diese Funktion in eine Promise basierte Funktion umzuwandeln, um alle diese verschachtelten Rückrufe und return Warnungen von ESLint consistent-return zu lösen.Umwandlung eines verschachtelten Callbacks in eine Promise

Zuvor habe ich um Hilfe gebeten, einen ESLint-Fehler mit meinen Rückgabeanweisungen zu umgehen, da sie nicht konsistent sind oder den Best Practices von JS folgen.

Mein erster Gedanke war einfach return new Promise((resolve, reject) => {...}) innerhalb der remove Funktion tun, aber das würde promisify nur das Ganze und nicht nur, was in der Funktion ist so ich so das Gefühl ist nicht der beste Weg, dies zu tun.

Jede Hilfe wird geschätzt!

function remove(req, res) { 
    User.findOne({ username: req.params.username }, (findErr, existingUser) => { 
    if (findErr) return res.status(500).send(errorHandler.getErrorMessage(findErr)); 
    if (!existingUser) return res.status(404).send({ message: 'User not found' }); 

    existingUser.remove((removeErr) => { 
     if (removeErr) return res.status(500).send(errorHandler.getErrorMessage(removeErr)); 

     return res.json({ message: `${existingUser.username} successfully deleted` }); 
    }); 
    }); 
} 
+1

Welche Bibliothek verwenden Sie für thsoe 'findOne' und' remove' Anrufe? Unterstützt es irgendwie Versprechen (möglicherweise durch einfaches Weglassen des Rückrufs)? – Bergi

+0

Verwenden Sie einfach Mungo für die Datenbankabfrage – germainelol

Antwort

2

Hier ist eine andere Möglichkeit, wie Sie es tun können. Ich begann mit "Promistifizieren" jeweils findOne und removeUser als separate Funktionen. Dann wird Ihre Route fast automatisch vereinfacht.

Es gibt noch einige Verbesserungen, die Sie hier machen könnten, aber vielleicht können Sie etwas daraus lernen.

(Danke @Bergi für die nützlichen Empfehlungen)

const error = (type, message) => Object.assign(new Error(message), {type}); 
const wrapError = type => err => { throw error(type, errorHandler.getErrorMessage(err));}; 

const findUser = opts => { 
    return new Promise((resolve, reject) => { 
    User.findOne(opts, (err, user) => { 
     if (err) reject(err); 
     else resolve(user); 
    }); 
    }).then(user => { 
    if (!user) throw error('USER_NOT_FOUND', 'User not found') 
    else return user; 
    }, wrapError('USER_FIND_ERROR')); 
}; 

const removeUser = user => { 
    return new Promise((resolve, reject) => { 
    user.remove(err => { 
     if (err) reject(err); 
     else resolve(); 
    }); 
    }).catch(wrapError('USER_REMOVE_ERROR')); 
}; 

function remove(req, res) { 
    findUser({ username: req.params.username }) 
    .then(removeUser) 
    .then(() => res.json({message: `${req.params.username} successfully removed`})) 
    .catch(error) => { 
     switch (error.type) { 
     case 'USER_NOT_FOUND': 
      return res.status(404).send(error.message); 
     // case 'USER_FIND_ERROR': 
     // case 'USER_REMOVE_ERROR': 
     default: 
      console.error(error.type, error.message, error.stack); 
      return res.status(500).send(error.message); 
     } 
    }); 
} 
+0

Ich würde empfehlen, die Promistification einfach zu halten und nur 'if (err) reject (err) sonst resolve (...);'. Wenn Sie etwas anderes benötigen, wie diese 'errorHandler.getErrorMessage' Aufrufe oder den Leerheitstest, tun Sie das in einem' then' oder 'catch' Handler. – Bergi

+0

Wie wäre es mit 'const error = (Typ, Nachricht) => Object.assign (neuer Fehler (Nachricht), {Typ});'? – Bergi

+0

@Bergi danke für die Vorschläge. Können Sie näher auf den ersten Kommentar eingehen, den Sie gemacht haben? Fühlen Sie sich frei, diese Antwort zu bearbeiten, wenn das einfacher ist^_^ – naomik

1

nicht sicher, ob Ihre Nummer bekommen, aber Sie können die folgenden

const findUser = (username) => { 
    return new Promise((resolve, reject) => { 
    User.findOne({ username }, (error, user) => { 
     if (error) { 
     reject({ type: 'error', details: errorHandler.getErrorMessage(error) }); 
     return; 
     } 

     if (!user) { 
     reject({ type: 'not-found', details: { message: 'User not found' } }); 
     return; 
     } 

     resolve(user); 
    }); 
    }); 
}; 

const removeUser = (username) => { 
    return new Promise((resolve, reject) => { 
    findUser(username) 
     .then(user => { 
     user.remove((error) => { 
      if (error) { 
      reject({ type: 'error', details: errorHandler.getErrorMessage(error) }); 
      return; 
      } 

      // Simply resolve on success 
      resolve(); 
     }); 
     }) 
     .catch(error => reject(error)); 
    }); 
}; 

function remove(req, res) { 
    removeUser(req.params.username) 
    .then(() => res.json({ message: `${req.params.username} successfully deleted` })) 
    .catch(error => { 
     if (error.type === 'not-found') { 
     return res.status(404).send(error.details); 
     } 

     return res.status(500).send(error.details); 
    }); 
} 

Wie Sie bemerkt haben oben könnte, einige der Verhaltensweisen ausprobieren wollen wurden Funktionen extrahiert, die Versprechungen zurück.

Hätte möglicherweise noch mehr optimiert, aber ich wollte Ihnen nur zeigen, was mit Promises möglich ist.

Hilft das?

+0

Interessant, so die Promise-Logik zu verwenden, würde es sowohl mein Rückrufproblem als auch mein Problem der konsistenten Rückgabe lösen. Um mich in die richtige Richtung zu weisen, welche Optimierungen meinten Sie, als Sie sagten, dass dies weiter optimiert werden könnte? Fragt, wie es mir gut aussieht. – germainelol

+2

Vermeiden Sie die ['Promise' Konstruktor Antipattern] (http://stackoverflow.com/q/23803743/1048572) in' removeUser'! – Bergi

+0

Hier ist eine leicht optimierte Version: https://gist.github.com/maciejsmolinski/c176cb27c5a2d81104acd95ce10715ca –

Verwandte Themen