Konvertieren von AWS Lambda-Funktion zu verwenden, was Sie verspricht?
Schreibe ich einen einfachen HTTP - 'ping' - Funktion wird periodisch ausgeführt, die mit AWS Lambda. Es verwendet vier asynchrone Funktionen: http.erhalten, S3.getObject, S3.putObject, und nodemailer.sendMail. Jeder scheint eine etwas unterschiedliche callback-Modell.
Nach der Lektüre über Versprechungen, ich verbrachte viel zu viel Zeit mit dem Versuch, konvertieren Sie den folgenden code verwenden Q Versprechungen und scheiterte kläglich.
Für meine Ausbildung und hoffentlich die der anderen, ich hatte gehofft, jemand könnte mir helfen, konvertieren diese zu verwenden verspricht (nicht 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: Ersten Versuch schriftlich mit Versprechungen:
'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);
});
};
Diese nicht ganz funktioniert. Die Ergebnis-Protokolle sind:
called 1
called 2
Last observed status: UP
called 3
called 4
Outcome of ping was: undefined
ReferenceError: resolve is not defined
InformationsquelleAutor GuruJ | 2016-11-06
Du musst angemeldet sein, um einen Kommentar abzugeben.
Konvertieren Sie Ihre typische async-Funktion, um ein Versprechen ist ziemlich straight-forward. Ich würde eher versuchen, und zeigen, wie es zu konvertieren als den code schreiben, wie Sie lernen nicht alles aus.
In der Regel mit Knoten haben Sie etwas, das so ähnlich aussieht wie diese:
Versprechen die Verpackung eines async-Funktion in der Regel wie folgt aussieht:
Übergeben das Ergebnis unten in der Kette unserer "immer dann" - Methode, die wir brauchen, um wieder ein Versprechen oder einen Wert:
Ich denke, dass mithilfe der oben genannten Muster sollten gerecht auf die meisten der asynchrone Methoden und Ereignisse in deinem code Beispiel, wenn alle, insbesondere diejenigen, die Ihnen Mühe schreiben Sie einen Kommentar und ich werde versuchen, diese spezifischen Beispiele.
Hier ist ein Versuch, konvertieren es verspricht - ich bin ziemlich müde, also entschuldige mich über alle mess-oder Fehler - auch da gibt es noch viel Aufräumen, was getan werden könnte.
Im wesentlichen, was ich getan habe, ist zu versuchen, brechen Sie den code in Aufgaben und wickeln Sie jede dieser Aufgaben ein Versprechen. Auf diese Weise können wir beheben/ablehnen und Kette Sie an.
Ich habe meine Aufnahme bei der Umwandlung es verspricht - ich bin ziemlich müde, also sorry wegen Fehlern. In der Regel ist es am besten zu brechen, Ihren code in kleine Aufgaben, die Rendite verspricht. Sie lösen eine Aufgabe, sobald es erfolgreich ist oder es ablehnen, wenn es nicht, übergeben Sie die "return" - Wert als argument zu beheben/abzulehnen, die dann an die nächste übergeben Sie dann/catch in der Kette zugewiesen, als der Wert, der als besonders vielversprechend. Einmal ein Versprechen aufgelöst wird oder abgelehnt, die es Wert ist unveränderlich. In Ihrem Versuch, die Sie versuchen zu lösen das Versprechen in sich ein .dann aber die Entschlossenheit und ablehnen, die Argumente sind out-of-scope
InformationsquelleAutor Brian
Um "promisify" callback-Funktion, die imho die einfachste und sauberer Weg ist bluebird. Wollen Sie nicht nur zu schreiben, glue-code, um den code vereinfachen, es ist kontraproduktiv (und es ist fehleranfällig).
Aus der doc :
InformationsquelleAutor Boris Charpentier
Das AWS-SDK unterstützt native verspricht, für alle Dienste. Einige benötigen zusätzliche Parameter, um die Rückkehr richtig, wie Lambda.invoke().
Würden Sie im wesentlichen tun
Oder, Sie könnte verwenden
async
/await
:Für den schnellen Zugriff auf die eigentliche Datei (nicht Metadaten):
https://docs.aws.amazon.com/sdk-for-javascript/v2/developer-guide/using-promises.html
InformationsquelleAutor slaughtr
Nach der Lektüre slaughtr die Antwort, die ich beschlossen, es zu tun wie diese, die das tun, einige Daten zu speichern, beim drücken der AWS IoT-Taste:
und kurz nachdem ich beschlossen, zu komprimieren, es noch weiter mit async/await
Ich bin noch ziemlich neu in diesem, async Programmierung Sachen, so dass ich nicht sicher bin, was sollte ich am meisten mag. Versprechen Verkettung kann man ein bisschen spaghetti-like, während async-await hilft nur Maske werden alle, die in etwas, das leichter zu begreifen,
InformationsquelleAutor powerslide