2016-04-21 1 views
0

Utiliser Monoskin dans la route express que je fais ce qui suit:Briser Callback Hell comment puis-je passer une valeur?

router.get(/getbuyerinfo, function(req, res) { 

    var data = "data"; 

    db.collection('buyerRec').find().toArray(function(err, result) { 
     if (err) throw err; 
     console.log(result); 

     db.collection('buyerHistory').find().toArray(function(err, result) { 
      if (err) throw err; 
      console.log(result); 
      console.log(data); 
     }); 
    }); 
}); 

Il est en fait beaucoup plus profond. Mais pour tenter de nettoyer les callbacks profondes, la plus directe de manière vers l'avant et le plus rapide, même si pas la façon la plus moderne, j'ai créé:

router.get(/getbuyerinfo, getBuyerRec); 

function getBuyerRec(req, res) { 
    var data = "data"; 

    db.collection('buyerRec').find().toArray(getBuyerHistory); 
} 

function getBuyerHistory(err, result) { 
    if (err) throw err; 
    console.log(result); 

    db.collection('buyerHistory').find().toArray(function(err, result) { 
     if (err) throw err; 
     console.log(result); 
     console.log(data); 
    }); 
} 

Mon problème est que « les données » n'est plus portée . La valeur 'data' provient de l'Express router.get(). Comment puis-je transmettre 'data' à la fonction getBuyerHistory pour pouvoir l'utiliser?

+0

votre exemple montre les données étant encore portée. – zzzzBov

+0

@zzzzBov ce serait mon rêve parce que c'est simple. Puis-je vous demander de m'expliquer votre compréhension? 'data' et le reste du code sont en fait dans une route Express, car je vais ajuster le code pour montrer. Donc, les «données» ne sont pas globales. Comment est-il dans la portée de la fonction getBuyerHistory? – Ric

+1

Jetez un oeil [ici] (http://stackoverflow.com/a/28250687/1048572) - application partielle est ce que vous cherchez. Même si la fermeture n'est pas faite par bind ou par partial, vous pouvez réduire votre imbrication à un maximum de deux niveaux. – Bergi

Répondre

1

supposant que vous avez quelque chose le long des lignes de:

(function() { 
    var data = "data"; 

    db.collection('buyerRec').find().toArray(getBuyerHistory); 
}()); 

function getBuyerHistory(err, result) { 
    if (err) throw err; 
    console.log(result); 

    db.collection('buyerHistory').find().toArray(function(err, result) { 
     if (err) throw err; 
     console.log(result); 
     console.log(data); 
    }); 
}); 

vous pouvez créer une fonction qui retourne une fonction, et passer data en tant que paramètre:

function factory(data) { 
    return function getBuyerHistory(err, result) { 
    ... 
    }; 
} 

que vous pouvez ensuite appeler pour créer la fonction que vous passez à toArray:

(function() { 
    var data = "data"; 

    db.collection('buyerRec').find().toArray(factory(data)); 
}()); 

alternativement, si vous n'êtes pas utiliser autrement this dans les getBuyerHistory, vous pouvez lier data que le contexte et passer la fonction liée à toArray:

(function() { 
    var data = "data"; 

    db.collection('buyerRec').find().toArray(getBuyerHistory.bind(data)); 
}()); 

alternativement, comme @Bergi souligné à juste titre, vous pouvez ajouter un autre paramètre à getBuyerHistory et utiliser bind sans contexte:

(function() { 
    var data = "data"; 

    db.collection('buyerRec').find().toArray(getBuyerHistory.bind(null, data)); 
}()); 

function getBuyerHistory(data, err, result) { 
    ... 
} 
+0

Que diriez-vous de 'makeBuyerHistoryGetter' au lieu de' factory'? :-) – Bergi

+0

'bind' fonctionne plus propre si vous ajoutez un paramètre à' getBuyerHistory' et que vous ne transmettez rien pour le contexte. – Bergi

+0

Ok, je n'ai pas beaucoup d'expérience. Je l'obtiens de faire.Et faire prend un moment. Mais mon exemple de code ci-dessus, que j'ai développé pour plus de contexte, est très simple. Le premier exemple, l'exemple de l'enfer du rappel fonctionne. Le refaire, avec ce que je crois apporte la portée perdue est simple aussi. Ces réponses semblent vraiment déformées, peut-être parce qu'elles sont avancées dans mon expérience. N'y a-t-il pas un moyen simple de passer les données var en bas de la ligne et de garder le code simple. Qu'en est-il du commentaire @zzzzBov qu'en fait la portée n'est pas perdue. Il me semble que c'est. – Ric