La conversion AWS Lambda fonction à utiliser promesses?
Je suis en train d'écrire un simple HTTP 'ping' fonction qui est d'être régulièrement exécutés à l'aide d'AWS Lambda. Il utilise quatre asynchrone fonctions: http.obtenir, S3.getObject, S3.putObject, et nodemailer.sendMail. Chacun semble avoir un peu différent modèle de rappel.
Après la lecture de promesses, j'ai passé beaucoup trop de temps à essayer de convertir le code suivant pour utiliser Q promesses et a échoué lamentablement.
Pour mon éducation et j'espère que d'autres personnes, j'espérais que quelqu'un pourrait m'aider à convertir ce à l'aide de promesses (n'a pas à être Q):
'use strict';
var http = require('http');
var nodemailer = require('nodemailer');
var AWS = require('aws-sdk');
var s3 = new AWS.S3( { params: { Bucket: 'my-bucket' } } );
exports.handler = (event, context, callback) => {
var lastStatus;
var options = {
host: event.server.host,
port: event.server.port ? event.server.port : 80,
path: event.server.path ? event.server.path : '',
method: event.server.method ? event.server.method : 'HEAD',
timeout: 5000
};
var transporter = nodemailer.createTransport({
host: event.mail.host,
port: event.mail.port ? event.mail.port : 587,
auth: {
user: event.mail.user,
pass: event.mail.pass
}
});
var d = new Date();
var UTCstring = d.toUTCString();
//email templates
var downMail = {
from: event.mail.from,
to: event.mail.to,
subject: 'Lambda DOWN alert: SITE (' + event.server.host + ') is DOWN',
text: 'LambdaAlert DOWN:\r\nSITE (' + event.server.host + ') is DOWN as at ' + UTCstring + '.'
};
var upMail = {
from: event.mail.from,
to: event.mail.to,
subject: 'Lambda UP alert: SITE (' + event.server.host + ') is UP',
text: 'LambdaAlert UP:\r\nSITE (' + event.server.host + ') is UP as at ' + UTCstring + '.'
};
//Run async chain to ensure that S3 calls execute in proper order
s3.getObject( { Key: 'lastPingStatus' }, (err, data) => {
//get last status from S3
if (err) { lastStatus = "UP"; } else {
lastStatus = data.Body.toString();
console.log("Last observed status: " + lastStatus);
}
http_request(options, lastStatus);
});
function http_request(requestOptions, lastStatus) {
var req = http.request(requestOptions, function(res) {
if (res.statusCode == 200) {
if (lastStatus == "DOWN") {
console.log('Email up notice sending...');
transporter.sendMail(upMail, function(error, info) {
if (error) {
console.log("ERROR: " + error);
callback(null, "ERROR: " + error);
} else {
console.log('No further details available.');
callback(null, 'Up message sent');
}
});
}
s3.putObject({ Key: 'lastPingStatus', Body: 'UP', ContentType: 'text/plain' }, (error, data) => { console.log("Saved last state as UP"); });
callback(null, 'Website is OK.');
}
});
req.on('error', function(e) {
if (lastStatus == "UP") {
console.log('Email down notice sending...');
transporter.sendMail(downMail, function(error, info) {
if (error) {
console.log("ERROR: " + error);
callback(null, "ERROR: " + error);
} else {
console.log('No further details available.');
callback(null, 'Down message sent');
}
});
s3.putObject({ Key: 'lastPingStatus', Body: 'DOWN', ContentType: 'text/plain' }, (error, data) => { console.log("Saved last state as DOWN"); });
callback(null, 'Website is DOWN.');
}
});
req.end();
}
};
EDIT: Première tentative d'écriture à l'aide de promesses:
'use strict';
var http = require('http');
var nodemailer = require('nodemailer');
var AWS = require('aws-sdk');
var s3 = new AWS.S3( { params: { Bucket: 'lambda-key-storage' } } );
exports.handler = (event, context, callback) => {
var lastStatus;
var options = {
host: event.server.host,
port: event.server.port ? event.server.port : 80,
path: event.server.path ? event.server.path : '',
method: event.server.method ? event.server.method : 'HEAD',
timeout: 5000
};
var transporter = nodemailer.createTransport({
host: event.mail.host,
port: event.mail.port ? event.mail.port : 587,
auth: {
user: event.mail.user,
pass: event.mail.pass
}
});
var d = new Date();
var UTCstring = d.toUTCString();
//email templates
var downMail = {
from: event.mail.from,
to: event.mail.to,
subject: 'Lambda DOWN alert: SITE (' + event.server.host + ') is DOWN',
text: 'LambdaAlert DOWN:\r\nSITE (' + event.server.host + ') is DOWN as at ' + UTCstring + '.'
};
var upMail = {
from: event.mail.from,
to: event.mail.to,
subject: 'Lambda UP alert: SITE (' + event.server.host + ') is UP',
text: 'LambdaAlert UP:\r\nSITE (' + event.server.host + ') is UP as at ' + UTCstring + '.'
};
var myProm = new Promise(function(resolve, reject) {
console.log("called 1");
s3.getObject( { Key: 'lastPingStatus' }, (err, data) => {
//get last status from S3
if (err) {
resolve("UP");
} else {
resolve(data.Body.toString());
}
});
})
.then(function(lastStatus) {
console.log("called 2");
console.log("Last observed status: " + lastStatus);
var req = http.request(options, function(res) {
resolve(res.statusCode);
});
req.on('error', function(e) {
reject(e);
});
req.end();
return "??";
})
.then(function(statusCode) {
console.log("called 3");
if (statusCode == 200) {
if (lastStatus == "DOWN") {
console.log('Email up notice sending...');
resolve("upTrigger");
} else {
resolve("upNoTrigger");
}
s3.putObject({ Key: 'lastPingStatus', Body: 'UP', ContentType: 'text/plain' }, (err, data) => { console.log("Saved last state as UP"); });
callback(null, 'Website is OK.');
}
})
.catch(function(err){
console.log("called 3 - error");
//Send mail notifying of error
if (lastStatus == "UP") {
console.log('Email down notice sending...');
resolve("downTrigger");
s3.putObject({ Key: 'lastPingStatus', Body: 'DOWN', ContentType: 'text/plain' }, (error, data) => { console.log("Saved last state as DOWN"); });
callback(null, 'Website is DOWN.');
return("downTrigger");
} else {
return "downNoTrigger";
}
})
.then(function(trigger) {
console.log("called 4");
if (trigger == "upTrigger") {
transporter.sendMail(upMail, (error, info) => {
if (error) {
console.log("ERROR: " + error);
callback(null, "ERROR: " + error);
} else {
console.log('Up message sent.');
callback(null, 'Up message sent');
}
});
} else if (trigger == "downTrigger") {
transporter.sendMail(downMail, (error, info) => {
if (error) {
console.log("ERROR: " + error);
callback(null, "ERROR: " + error);
} else {
console.log('Down message sent.');
callback(null, 'Down message sent');
}
});
}
console.log("Outcome of ping was: ", trigger);
});
};
Ce n'est pas tout à fait. Le résultat journaux sont:
called 1
called 2
Last observed status: UP
called 3
called 4
Outcome of ping was: undefined
ReferenceError: resolve is not defined
OriginalL'auteur GuruJ | 2016-11-06
Vous devez vous connecter pour publier un commentaire.
La conversion de votre asynchrone classique de la fonction à une promesse est assez simple. Je préfère essayer et de démontrer comment le convertir que d'écrire le code que vous n'avez pas apprendre quelque chose de cela.
Généralement avec le noeud, vous aurez quelque chose qui ressemble à ceci:
Une promesse d'habillage d'une fonction async généralement ressemble à quelque chose comme ceci:
À transmettre le résultat de la chaîne de nos "toujours" méthode nous avons besoin du retour d'une promesse ou d'une valeur:
Je pense que l'utilisation de ces tendances devraient répondre à la plupart des méthodes asynchrones et les événements dans votre exemple de code si tout particulier ceux sont de vous donner de la difficulté à déposer un commentaire et je vais essayer de couvrir ces exemples précis.
Voici une tentative de le convertir plus de promesses - je suis assez fatigué alors, toutes mes excuses à propos de tout désordre ou d'erreurs, d'ailleurs, il y a encore beaucoup de nettoyage qui pourrait en être fait.
Essentiellement ce que j'ai fait c'est d'essayer de briser le code des tâches et envelopper chacune de ces tâches en une promesse. De cette façon, nous pouvons résoudre ou de rejeter et de la chaîne.
J'ai ajouté mon coup à la conversion à des promesses, je suis assez fatiguée, donc désolé pour les erreurs. Généralement, il est préférable de casser votre code en petites tâches qui renvoient des promesses. La résolution d'une tâche une fois c'est un succès ou de le rejeter si elle ne parvient pas, vous passez le "retour" de la valeur comme argument pour résoudre ou de rejeter ce qui est ensuite transmis à l'autre, alors/catch dans la chaîne et affecté en tant que valeur de cette promesse. Une fois une promesse est résolu ou rejeté sa valeur est immuable. Dans votre tentative, vous essayez de résoudre la promesse à l'intérieur d'un .ensuite, mais de volonté et de rejeter les arguments sont hors de portée
OriginalL'auteur Brian
Pour "promisify" fonction de rappel, à mon humble avis, le plus simple et le plus propre est d'utiliser bluebird. Vous n'avez tout simplement pas envie d'écrire colle le code dans le but de simplifier votre code, il est contre-productif (et c'est source d'erreurs).
De la doc :
OriginalL'auteur Boris Charpentier
L'AWS SDK prend en charge les promesses, pour tous les services. Certains ont besoin de paramètres supplémentaires pour retourner correctement, comme un Lambda.invoke().
Vous serait essentiellement le faire
Ou, vous pouvez utiliser
async
/await
:Pour un accès rapide à la taille réelle du fichier (et non pas de métadonnées):
https://docs.aws.amazon.com/sdk-for-javascript/v2/developer-guide/using-promises.html
OriginalL'auteur slaughtr
Après la lecture de slaughtr de réponse, j'ai décidé de faire comme ça, pour faire des sauvegarde des données lors de l'appui sur AWS IoT bouton:
et peu de temps après, j'ai décidé de le compresser encore plus loin avec async/await
Je suis encore assez nouveau à cette programmation asynchrone de choses donc je ne suis pas sûr de ce que je voudrais le plus. Promesse de chaînage peut être un peu comme des spaghettis, tandis que async n'attendent plus que aide du masque en quelque chose qui est plus facile à comprendre
OriginalL'auteur jsaddwater