dans le code ci-dessous suis-je dans callbackhell? Comment surmonter un tel scénario sans utiliser de modules ASYNC dans Pure JavaScript? Le code ci-dessus est copié dans plusieurs emplacements pour faire fonctionner le code comme prévu. p>
3 Réponses :
Oui, vous êtes en enfer de rappel. La solution supposant que vous ne voulez pas utiliser ASYNC (que je doute que vous puissiez justifier autrement que le préjudice) consiste en:
1 fort>) fait plus de fonctions de niveau supérieur. Chaque fonction doit effectuer 1 ou 2 opérations IO en règle générale. P> 2 strong>) Appelez ces fonctions, ce qui fait que votre code suive une structure d'une longue liste de fonctions de base courtes Organisé en logique commerciale par une petite liste de flux de contrôle «Colle» fonctions. p> au lieu de: p> objectif pour: p> function saveDb1(arg1, arg2, callback) {//top-level code}
function saveDb2(arg1, arg2, callback) {//top-level code}
function sendEmail(arg1, arg2, callback) {//top-level code}
function businessLogic(){//uses the above to get the work done}
Je suppose que je devrais utiliser la bibliothèque Async.
Il est bon de savoir comment utiliser des rappels simples sans entrer en enfer. Apprenez ensuite à utiliser les événements de base pour obtenir des résultats similaires, le cas échéant. Ensuite, considérons des promesses. Mais en fin de compte lors de la rédaction d'une application Web et que chaque requête implique généralement 3 opérations d'E / S qui doivent être effectuées en série ou en parallèle, oui, vous voulez probablement apprendre à utiliser une bibliothèque de flux de contrôle telle que ASYNC, Nimble, étape, ou similaire.
Bonjour, devrais-je utiliser async.servies ou async.fall dans cette condition?
J'ai un argument pourquoi je n'utilise pas ASYNC ni d'autres bibliothèques d'assistance telles que le soulignement ou les promesses. Ces 3 libs, pour moi, polluent le code. Vanilla JS est simple, facile, vous n'avez pas besoin d'utiliser une fonction de boîte noire pour exécuter des fonctions asynchrones «parallèles», il vous suffit de comprendre comment travailler. Si vous organisez votre code, vous n'avez pas besoin de boîtes noires pour des trucs faciles comme ça.
@askkirati commence par série code> &
cascade code> car ils sont plus faciles à comprendre. Finalement, lorsque vous comprenez les vraies dépendances ou l'absence de ceux-ci entre vos opérations, vous pouvez passer à
parallèle code> et peut-être une vitesse de certaines choses.
Dans la section "Viser" ", j'aimerais y voir un exemple. Mon expérience est que j'aimerais concevoir cela, mais quand je le fais, BusinessLogic () code> est exécuté avant
sauvegardéb1 () code> est terminé.
"Si vous essayez de coder BussSiness DB Connectez-vous en utilisant pur nœud.js, vous allez directement à Callback Hell" em> J'ai récemment créé une abstraction simple nommée waitfor pour appeler des fonctions asynchrones Mode synchronisé (basé sur des fibres): https://github.com/luciotato/waitfor P> Vérifiez l'exemple de la base de données: P> pure nœud.js (HELLE de rappel léger): p> Exemple de base de données (pseudocode) h2>
//run in a Fiber
function processInviteEmails(email_list, user_id, emailCallBack, completionCallback){
while (email_list.length) {
var email = email_list.pop();
try {
check(email).isEmail(); //is valid email or throw
var connected_data = wait.for(checkConnected,email,user_id);
if(connected_data.connect_status !== 'not connected') throw new Error('Already connected');
//insert to connect and send msg to queue
var cur_date = moment().format('YYYY-MM-DD');
var dbData = {
"first_name": '',
"last_name": '',
"email": email,
"user_id": user_id,
"status": "invited",
"unsubscribe_token": crypto.randomBytes(6).toString('base64'),
"created": cur_date,
"modified": cur_date
};
result = wait.forMethod(ConnectModel,'insert',dbData);
// ConnectModel.insert shuold have a fn(err,data) as callback, and return something in err if (data.insertId <= 0)
//send to email queue
//Queue Email
res_data = wait.forMethod(MailTemplateModel,'getTemplateData','invitation');
// MailTemplateModel.getTemplateData shuold have a fn(err,data) as callback
// inside getTemplateData, callback with err=new Error('Unable to get email template') if (data.status !== 'success')
var unsubscribe_hash = crypto.createHash("md5")
.update(dbData.unsubscribe_token + email)
.digest('hex');
var unsubscribe_link = app.locals.SITE_URL+'/unsubscribe/' + result.insertId + '/' + unsubscribe_hash;
var template_row = res_data.template_row;
var user_full_name = user_row.user_firstname+' '+ user_row.user_lastname;
var invitation_link = 'http://'+user_row.url_alias+'.'+ app.locals.SITE_DOMAIN;
var mailOptions = {
"type": 'invitation',
"to": dbData.email,
"from_name" : user_full_name,
"subject": template_row.message_subject
.replace('[[USER]]', user_full_name),
"text": template_row.message_text_body
.replace('[[USER]]', user_full_name)
.replace('[[INVITATION_LINK]]', invitation_link)
.replace('[[UNSUBSCRIBE_LINK]]', unsubscribe_link),
"html": template_row.message_body
.replace('[[USER]]', user_full_name)
.replace('[[INVITATION_LINK]]', invitation_link)
.replace('[[UNSUBSCRIBE_LINK]]', unsubscribe_link)
};
mailOptions = JSON.stringify(mailOptions);
//send email to queue ... callback(err,data)
wait.forMethod(sqsHelper,'addToQueue',cfg.sqs_invitation_url, mailOptions);
} catch (e) {
// one of the callback returned err!==null
emailCallBack(e, email);
}
} // loop while length>0
completionCallback();
}
// run the loop in a Fiber (keep node spinning)
wait.launchFiber(processInviteEmails,email_list, user_id, emailCallBack, completionCallback);
J'ai mis une autre solution dans Mon blog < / a>. C'est laid mais c'est la chose la plus lisible que je puisse faire avec pure JavaScript.
Pourquoi avez-vous besoin de l'essai / attraper? Normalement, des erreurs sont transmises au rappel, et cela devrait couper le niveau d'indentation de moitié
Pour répondre à la moitié de la question: Oui, vous êtes en enfer de rappel. Vous voudrez probablement présenter une certaine abstraction; Si vous êtes opposé aux bibliothèques de contrôle de contrôle existantes, vous voudrez probablement que vous souhaitiez probablement écrire une fonction code> de la série code> vous-même.