JavaScript-Problem, wenn Datenquelle nicht erreichbar
Hallo zusammen,
ich habe hier ein JavaScript, welches ich von einem Teilnehme des SelfHTML-Forum bekommen und geringfügig angepaßt habe (zum Thread hier klicken). Leider meldet sich der damalige Autor des Scriptes nicht mehr, so daß ich hoffe, daß mir hier jemand weiterhelfen kann.
Das Script hat die Aufgabe, auf einem Schaufenster-PC die Tagesschau-News aus dem RSS-Feed von tagesschau.de in Endlosschleife durchlaufen zu lassen. Das klappte bis vor ein paar Wochen auch völlig problemlos. In letzter Zeit kommt es aber immer häufiger mal vor, daß die Seite plötzlich leer bleibt und keine News mehr angezeigt werden.
Meine Vermutung dazu ist folgende: Ich habe festgestellt, daß der Tagesschau-Server ab und zu für ein paar Sekunden nicht erreichbar ist. Wenn das gerade dann passiert, wenn die News einmal durchgelaufen sind und der Feed neu geladen werden muß, dann klappt es mit dem Laden nicht, und dann scheint der Ablauf unterbrochen zu sein und die Seite bleibt leer.
Wenn das so ist, dann kann man da doch sicher eine Fehler-Abfangroutine einbauen, die, wenn der Feed gerade nicht geladen werden kann (oder query.yahooapis.com nicht erreichbar ist), in eine Warteschleife geht und es nach ein paar Sekunden noch mal probiert. Ich habe da Verschiedenes probiert, aber ich kenne mich mit JavaScript zu wenig aus, um da erfolgreich zu sein. Hat von Euch jemand eine Idee?
Hier ist erst mal das Script bzw. die komplette HTML-Datei:
Laufen soll das ganze mit einem aktuellen Firefox.
Für zielführende Tipps Danke im Voraus,
Sarek
ich habe hier ein JavaScript, welches ich von einem Teilnehme des SelfHTML-Forum bekommen und geringfügig angepaßt habe (zum Thread hier klicken). Leider meldet sich der damalige Autor des Scriptes nicht mehr, so daß ich hoffe, daß mir hier jemand weiterhelfen kann.
Das Script hat die Aufgabe, auf einem Schaufenster-PC die Tagesschau-News aus dem RSS-Feed von tagesschau.de in Endlosschleife durchlaufen zu lassen. Das klappte bis vor ein paar Wochen auch völlig problemlos. In letzter Zeit kommt es aber immer häufiger mal vor, daß die Seite plötzlich leer bleibt und keine News mehr angezeigt werden.
Meine Vermutung dazu ist folgende: Ich habe festgestellt, daß der Tagesschau-Server ab und zu für ein paar Sekunden nicht erreichbar ist. Wenn das gerade dann passiert, wenn die News einmal durchgelaufen sind und der Feed neu geladen werden muß, dann klappt es mit dem Laden nicht, und dann scheint der Ablauf unterbrochen zu sein und die Seite bleibt leer.
Wenn das so ist, dann kann man da doch sicher eine Fehler-Abfangroutine einbauen, die, wenn der Feed gerade nicht geladen werden kann (oder query.yahooapis.com nicht erreichbar ist), in eine Warteschleife geht und es nach ein paar Sekunden noch mal probiert. Ich habe da Verschiedenes probiert, aber ich kenne mich mit JavaScript zu wenig aus, um da erfolgreich zu sein. Hat von Euch jemand eine Idee?
Hier ist erst mal das Script bzw. die komplette HTML-Datei:
<!doctype html>
<html>
<head>
<title>Tagesschau Ticker</title>
<!-- Hier holen wir uns erst mal jQuery von einem Google server damit wir das nicht selbst hosten müssen. -->
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.5/jquery.min.js"></script>
<script>
var DELAY = 10000; // 10 Sekunden pro Nachricht
// Yahoo bietet einen coolen Service an mit dem man feeds nach JSON umwandeln lassen kann
// und das sogar mit einer Callbackfunktion, ich habe sie hier mal 'callbackf' genannt.
// Ich habe mal eine URL gebastelt die die daten vom Tageschau-Server holt.
// Mehr dazu gibt es unter: http://developer.yahoo.com/yql/
var URL = "http://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20feed%20where%20url%3D'http%3A%2F%2Fwww.tagesschau.de%2Fxml%2Frss2'&format=json&callback=callbackf";
// Um einen extra server zum holen der Daten zu umgehen nutzen wir Yahoos YQL service mit einer
// callback funktion. Dazu machen wir uns einen neuen script-tag und fügen ihn in den Body ein.
// Dieser läd die daten von Yahoo und ruft gleichzeitig die callbackf-Funktion auf.
function reload() {
var s = document.createElement("script");
s.src = URL;
s.id = "datascript";
document.body.appendChild(s);
}
// Wenn das HTML geladen ist dann können wir die funktion reload() zum ersten mal aufrufen
$(document).ready(reload);
// Wird vom Script aufgerufen das von Yahoo kommt. Es werden die Daten des Feeds im JSON
// Format übergeben.
function callbackf(data)
{
// Damit der Speicher nicht voll läuft wenn das den ganzen Tag im Schaufenster läuft
// machen wir das script-tag mal weg, brauchen wir ja nicht mehr
$("#datascript").remove();
// Die items sind ja etwas tiefer im JSON drinn, die speichern wir mal in einer neuen Variable
var items = data.query.results.item;
// Ich mache es mir hier einfach und baue den Inhalt komplett in einen String den ich dann mit
// innerHTML() einfüge, das ist so weit erst mal übersichtlicher und geht geht fast
// genauso schnell.
var content = "";
for (var i = 0; i < items.length; i++)
{
content += "<li>";
content += "<h1>" + items[i].title + "</h1>";
content += "<p>" + items[i].description + "</p>";
content += "</li>";
}
// Hier setzen wir den content ins <ul> rein
$("#list").html(content);
// Hier verstecken wir jedes <li> damit alle erst mal unsichtbar sind
$("#list li").each(function (i, elem)
{
$(elem).hide();
});
// Hier zeigen wir das erste <li> mit einem fade-effekt an. Wenn dieser effekt fertig
// ist rufen wir die Funktion showNext() als callback auf (siehe dazu die jQuery doku für fadeIn())
$("#list li:first-child").fadeIn("slow", showNext);
}
// Diese funktion fadet das sichtbare <li> aus, entfernt es aus dem dom und fadet das nächste
// element ein.
function showNext()
{
var first_child = $("#list li:first-child");
// Die jQuery-delay() funktion wartet mit der ausführung des nächsten so lange wie
// in DELAY angegeben. Danach fird fadeOut() aufgerufen, sobald das fertig ist
// wird die hier angegebene namenlose callback-funktion aufgerufen
first_child.delay(DELAY).fadeOut('slow', function() {
// Erst entfernen wir das erste <li>
first_child.remove();
// dann holen wir uns das jetzt neue erste element (weil das andere ja weg ist)
var next_child = $("#list li:first-child");
if (next_child.length > 0)
{
// Wenn es noch ein Element in der <ul> gibt dann wird das reingefadet und
// wenn fertig die funktion showNext() wieder aufgerufen.
next_child.fadeIn('slow', showNext);
}
else
{
// Falls keine <li>s mehr zur Verfügung stehen starten wir das Script wieder von vorne
reload();
}
});
}
</script>
<style type="text/css">
/* Das CSS muss natürlich noch an die jeweiligen Bedürfnisse angepasst werden */
* { margin: 15; padding: 0; }
body { font-family: Verdana, Helvetica, sans-serif; background-color: #013773;}
h1 {font-size: 24pt; color: #ffffff; text-align: left;}
p {font-size: 20pt; color: #ffffff; text-align: left;}
ul { list-style-type: none; }
li { position: absolute; top: 20; left: 0; width: 480px; }
</style>
</head>
<body>
<img style="border-width: 2px; border-style: solid; border-color: #ffffff;" src="logo_tagesschau24.png" align="center">
<ul id="list">
<!-- Dies hier ist unser Container in den wir alle Daten reinladen werden. -->
</ul>
</body>
</html>
Laufen soll das ganze mit einem aktuellen Firefox.
Für zielführende Tipps Danke im Voraus,
Sarek
Bitte markiere auch die Kommentare, die zur Lösung des Beitrags beigetragen haben
Content-ID: 203395
Url: https://administrator.de/forum/javascript-problem-wenn-datenquelle-nicht-erreichbar-203395.html
Ausgedruckt am: 12.04.2025 um 14:04 Uhr
13 Kommentare
Neuester Kommentar
Hi Sarek,
habe dein Code folgendermaßen geändert:
Da das Yahoo API bei einem Fehler in den JSON-Callback-Daten in dem Eigenschaftenfeld count die Anzahl der zurückgegebenen Elemente auf 0 setzt können wir darauf in dem Script reagieren. Für den Fall das zwischendurch die Verbindung zum Tagesschau-Server ausfällt, legt sich das Script in der globalen Variable CURRENTSTREAM ein Backup der Nachrichten an und zeigt diese an. Nach diesem Durchlauf der Nachrichten holt es erneut aktuelle Daten. Ist der Tagesschau-Server beim ersten Aufruf der Seite nicht erreichbar wird der Vorgang jede Sekunde wiederholt, bis Daten vorliegen.
Die Änderungen findest du in Zeile 8
und Zeile 39-50
Der gesamte geänderte Code:
Grüße Uwe
habe dein Code folgendermaßen geändert:
Da das Yahoo API bei einem Fehler in den JSON-Callback-Daten in dem Eigenschaftenfeld count die Anzahl der zurückgegebenen Elemente auf 0 setzt können wir darauf in dem Script reagieren. Für den Fall das zwischendurch die Verbindung zum Tagesschau-Server ausfällt, legt sich das Script in der globalen Variable CURRENTSTREAM ein Backup der Nachrichten an und zeigt diese an. Nach diesem Durchlauf der Nachrichten holt es erneut aktuelle Daten. Ist der Tagesschau-Server beim ersten Aufruf der Seite nicht erreichbar wird der Vorgang jede Sekunde wiederholt, bis Daten vorliegen.
Die Änderungen findest du in Zeile 8
var CURRENTSTREAM = "";
//Änderungen für den Fall das der Tagesschau-Server ausfällt oder ein Fehler auftritt
var items;
if (data.query.count > 0) {
items = data.query.results.item;
CURRENTSTREAM = items;
}else{
if (CURRENTSTREAM != ""){
items = CURRENTSTREAM;
}else{
window.setTimeout("reload()",1000);
}
}
<!doctype html>
<html>
<head>
<title>Tagesschau Ticker</title>
<!-- Hier holen wir uns erst mal jQuery von einem Google server damit wir das nicht selbst hosten müssen. -->
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.5/jquery.min.js"></script>
<script>
var CURRENTSTREAM = "";
var DELAY = 10000; // 10 Sekunden pro Nachricht
// Yahoo bietet einen coolen Service an mit dem man feeds nach JSON umwandeln lassen kann
// und das sogar mit einer Callbackfunktion, ich habe sie hier mal 'callbackf' genannt.
// Ich habe mal eine URL gebastelt die die daten vom Tageschau-Server holt.
// Mehr dazu gibt es unter: http://developer.yahoo.com/yql/
var URL = "http://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20feed%20where%20url%3D'http%3A%2F%2Fwww.tagesschau.de%2Fxml%2Frss2'&format=json&callback=callbackf";
// Um einen extra server zum holen der Daten zu umgehen nutzen wir Yahoos YQL service mit einer
// callback funktion. Dazu machen wir uns einen neuen script-tag und fügen ihn in den Body ein.
// Dieser läd die daten von Yahoo und ruft gleichzeitig die callbackf-Funktion auf.
function reload() {
var s = document.createElement("script");
s.src = URL;
s.id = "datascript";
document.body.appendChild(s);
}
// Wenn das HTML geladen ist dann können wir die funktion reload() zum ersten mal aufrufen
$(document).ready(reload);
// Wird vom Script aufgerufen das von Yahoo kommt. Es werden die Daten des Feeds im JSON
// Format übergeben.
function callbackf(data)
{
// Damit der Speicher nicht voll läuft wenn das den ganzen Tag im Schaufenster läuft
// machen wir das script-tag mal weg, brauchen wir ja nicht mehr
$("#datascript").remove();
//Änderungen für den Fall das der Tagesschau-Server ausfällt oder ein Fehler auftritt
var items;
if (data.query.count > 0) {
items = data.query.results.item;
CURRENTSTREAM = items;
}else{
if (CURRENTSTREAM != ""){
items = CURRENTSTREAM;
}else{
window.setTimeout("reload()",1000);
}
}
// Ich mache es mir hier einfach und baue den Inhalt komplett in einen String den ich dann mit
// innerHTML() einfüge, das ist so weit erst mal übersichtlicher und geht geht fast
// genauso schnell.
var content = "";
for (var i = 0; i < items.length; i++)
{
content += "<li>";
content += "<h1>" + items[i].title + "</h1>";
content += "<p>" + items[i].description + "</p>";
content += "</li>";
}
// Hier setzen wir den content ins <ul> rein
$("#list").html(content);
// Hier verstecken wir jedes <li> damit alle erst mal unsichtbar sind
$("#list li").each(function (i, elem)
{
$(elem).hide();
});
// Hier zeigen wir das erste <li> mit einem fade-effekt an. Wenn dieser effekt fertig
// ist rufen wir die Funktion showNext() als callback auf (siehe dazu die jQuery doku für fadeIn())
$("#list li:first-child").fadeIn("slow", showNext);
}
// Diese funktion fadet das sichtbare <li> aus, entfernt es aus dem dom und fadet das nächste
// element ein.
function showNext()
{
var first_child = $("#list li:first-child");
// Die jQuery-delay() funktion wartet mit der ausführung des nächsten so lange wie
// in DELAY angegeben. Danach fird fadeOut() aufgerufen, sobald das fertig ist
// wird die hier angegebene namenlose callback-funktion aufgerufen
first_child.delay(DELAY).fadeOut('slow', function() {
// Erst entfernen wir das erste <li>
first_child.remove();
// dann holen wir uns das jetzt neue erste element (weil das andere ja weg ist)
var next_child = $("#list li:first-child");
if (next_child.length > 0)
{
// Wenn es noch ein Element in der <ul> gibt dann wird das reingefadet und
// wenn fertig die funktion showNext() wieder aufgerufen.
next_child.fadeIn('slow', showNext);
}
else
{
// Falls keine <li>s mehr zur Verfügung stehen starten wir das Script wieder von vorne
reload();
}
});
}
</script>
<style type="text/css">
/* Das CSS muss natürlich noch an die jeweiligen Bedürfnisse angepasst werden */
* { margin: 15; padding: 0; }
body { font-family: Verdana, Helvetica, sans-serif; background-color: #013773;}
h1 {font-size: 24pt; color: #ffffff; text-align: left;}
p {font-size: 20pt; color: #ffffff; text-align: left;}
ul { list-style-type: none; }
li { position: absolute; top: 20; left: 0; width: 480px; }
</style>
</head>
<body>
<img style="border-width: 2px; border-style: solid; border-color: #ffffff;" src="logo_tagesschau24.png" align="center">
<ul id="list">
<!-- Dies hier ist unser Container in den wir alle Daten reinladen werden. -->
</ul>
</body>
</html>
Grüße Uwe
Du kannst die Erreichbarkeit einer Seite mit Ajax überprüfen. Eine solche Funktion könnte mit jQuery-Ajax z.B. so aussehen:
Diese könntest du dann in die reload() Funkton einbauen:
Die jQuery Libraries die Google zur Verfügung stellt kannst du hier nachlesen(nimm am besten eine neuere Version):
https://developers.google.com/speed/libraries/devguide?hl=fr#jquery
happy coding
Uwe
function ping(){
$.ajax({
url: 'http://query.yahooapis.com',
success: function(result){
return true;
},
error: function(result){
return false;
}
});
}
Diese könntest du dann in die reload() Funkton einbauen:
function ping(targetURL){
$.ajax({
url: targetURL,
success: function(result){
return true;
},
error: function(result){
return false;
}
});
}
function reload() {
if (ping('http://query.yahooapis.com') == true){
var s = document.createElement("script");
s.src = URL;
s.id = "datascript";
document.body.appendChild(s);
}else{
window.setTimeout("reload()",2000);
}
}
Die jQuery Libraries die Google zur Verfügung stellt kannst du hier nachlesen(nimm am besten eine neuere Version):
https://developers.google.com/speed/libraries/devguide?hl=fr#jquery
happy coding
Uwe
Sorry da war ich zu schnell mit meinen Code-Schnippseln (Bin im Moment mit allen möglichen Programmiersprachen zu gange,da passiert so was mal). Das obige funktioniert leider nicht da bei Ajax die same origin policy restriction im Browser greift, was bedeutet das du damit nicht andere Domains auf Verfügbarkeit prüfen kannst.
Melde mich später nochmal ...
Melde mich später nochmal ...
Kann man diese Policy im Firefox irgendwo ausschalten? Es muß ja nur auf einem einzigen Browser laufen, und den kann ich ja
so konfigurieren, daß es geht (wenn man das denn konfigurieren kann).
Zusammen mit diesem AddIn für Firefox: https://addons.mozilla.org/en-US/firefox/addon/forcecors/so konfigurieren, daß es geht (wenn man das denn konfigurieren kann).
('Du aktivierst es in der Statusleiste mit Klick auf CORS; es ist dann rot eingefärbt)
und zusammen mit diesem Code hat es bei mir funktioniert:
<!doctype html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Tagesschau Ticker</title>
<!-- Hier holen wir uns erst mal jQuery von einem Google server damit wir das nicht selbst hosten müssen. -->
<script src="Programmierung/HTML5/jquery-1.7.min.js"></script>
<script type="text/javascript">
var CURRENTSTREAM = "";
var DELAY = 10000; // 10 Sekunden pro Nachricht
// Yahoo bietet einen coolen Service an mit dem man feeds nach JSON umwandeln lassen kann
// und das sogar mit einer Callbackfunktion, ich habe sie hier mal 'callbackf' genannt.
// Ich habe mal eine URL gebastelt die die daten vom Tageschau-Server holt.
// Mehr dazu gibt es unter: http://developer.yahoo.com/yql/
var URL = "http://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20feed%20where%20url%3D'http%3A%2F%2Fwww.tagesschau.de%2Fxml%2Frss2'&format=json&callback=callbackf";
// Um einen extra server zum holen der Daten zu umgehen nutzen wir Yahoos YQL service mit einer
// callback funktion. Dazu machen wir uns einen neuen script-tag und fügen ihn in den Body ein.
// Dieser läd die daten von Yahoo und ruft gleichzeitig die callbackf-Funktion auf.
function reload() {
$.ajax({
url: 'http://query.yahooapis.com',
cache:false,
success: function(result){
var s = document.createElement("script");
s.src = URL;
s.id = "datascript";
document.body.appendChild(s);
},
error: function(result){
if (CURRENTSTREAM == ""){
window.setTimeout("reload()",2000);
}else{
callbackf(CURRENTSTREAM);
}
}
});
}
// Wenn das HTML geladen ist dann können wir die funktion reload() zum ersten mal aufrufen
$(document).ready(reload);
// Wird vom Script aufgerufen das von Yahoo kommt. Es werden die Daten des Feeds im JSON
// Format übergeben.
function callbackf(data)
{
// Damit der Speicher nicht voll läuft wenn das den ganzen Tag im Schaufenster läuft
// machen wir das script-tag mal weg, brauchen wir ja nicht mehr
$("#datascript").remove();
//Änderungen für den Fall das der Tagesschau-Server ausfällt oder ein Fehler auftritt
var items;
if (data.query.count > 0) {
items = data.query.results.item;
CURRENTSTREAM = data;
}else{
if (CURRENTSTREAM !== ""){
items = CURRENTSTREAM.query.results.item;
}else{
window.setTimeout("reload()",1000);
}
}
// Ich mache es mir hier einfach und baue den Inhalt komplett in einen String den ich dann mit
// innerHTML() einfüge, das ist so weit erst mal übersichtlicher und geht geht fast
// genauso schnell.
var content = "";
for (var i = 0; i < items.length; i++)
{
content += "<li>";
content += "<h1>" + items[i].title + "</h1>";
content += "<p>" + items[i].description + "</p>";
content += "</li>";
}
// Hier setzen wir den content ins <ul> rein
$("#list").html(content);
// Hier verstecken wir jedes <li> damit alle erst mal unsichtbar sind
$("#list li").each(function (i, elem)
{
$(elem).hide();
});
// Hier zeigen wir das erste <li> mit einem fade-effekt an. Wenn dieser effekt fertig
// ist rufen wir die Funktion showNext() als callback auf (siehe dazu die jQuery doku für fadeIn())
$("#list li:first-child").fadeIn("slow", showNext);
}
// Diese funktion fadet das sichtbare <li> aus, entfernt es aus dem dom und fadet das nächste
// element ein.
function showNext()
{
var first_child = $("#list li:first-child");
// Die jQuery-delay() funktion wartet mit der ausführung des nächsten so lange wie
// in DELAY angegeben. Danach fird fadeOut() aufgerufen, sobald das fertig ist
// wird die hier angegebene namenlose callback-funktion aufgerufen
first_child.delay(DELAY).fadeOut('slow', function() {
// Erst entfernen wir das erste <li>
first_child.remove();
// dann holen wir uns das jetzt neue erste element (weil das andere ja weg ist)
var next_child = $("#list li:first-child");
if (next_child.length > 0)
{
// Wenn es noch ein Element in der <ul> gibt dann wird das reingefadet und
// wenn fertig die funktion showNext() wieder aufgerufen.
next_child.fadeIn('slow', showNext);
}
else
{
// Falls keine <li>s mehr zur Verfügung stehen starten wir das Script wieder von vorne
reload();
}
});
}
</script>
<style type="text/css">
/* Das CSS muss natürlich noch an die jeweiligen Bedürfnisse angepasst werden */
* { margin: 15; padding: 0; }
body { font-family: Verdana, Helvetica, sans-serif; background-color: #013773;}
h1 {font-size: 24pt; color: #ffffff; text-align: left;}
p {font-size: 20pt; color: #ffffff; text-align: left;}
ul { list-style-type: none; }
li { position: absolute; top: 20; left: 0; width: 480px; }
</style>
</head>
<body>
<img style="border-width: 2px; border-style: solid; border-color: #ffffff;" src="logo_tagesschau24.png" align="center">
<ul id="list">
<!-- Dies hier ist unser Container in den wir alle Daten reinladen werden. -->
</ul>
</body>
</html>
> Nach einem Neustart von Firefox ist das CORS-AddOn wieder inaktiv und müßte neu per Mausklick aktiviert werden.
Schicke Dir per PN das modifizierte CORS-AddIn mit beim Start von Firefox aktiviertern CORS-Headern. Die Option es an und auszuschalten habe ich entfernt. Das sollte dein Problem lösen.Oder kann sonst vielleicht das hier helfen? Ich verstehe
Das geht auch nur wenn du CORS mit dem AddOn aktivierst.
Habe noch eine Alternative für dich die auch ohne CORS im Browser funktioniert:
Diese versucht ein kleines Bild auf einer Seite von Yahoo zu laden(Um das Cachen des Bildes zu umgehen wird bei jedem laden des kleinen Bildes die Uhrzeit als Querystring mit angehängt). Wenn dies gelingt fährt das Script normal fort ansonsten wiederholt es den Vorgang alle 2 Sekunden.
ersetzte die reload()-Funktion durch diese:
Grüße Uwe
Diese versucht ein kleines Bild auf einer Seite von Yahoo zu laden(Um das Cachen des Bildes zu umgehen wird bei jedem laden des kleinen Bildes die Uhrzeit als Querystring mit angehängt). Wenn dies gelingt fährt das Script normal fort ansonsten wiederholt es den Vorgang alle 2 Sekunden.
ersetzte die reload()-Funktion durch diese:
function reload() {
var imgObject = new Image();
imgObject.src = "http://l.yimg.com/a/i/us/pps/breadcrumb-arrow.gif?pingdat=" + new Date().getTime();
window.setTimeout(function(){
if (imgObject.height > 0){
var s = document.createElement("script");
s.src = URL;
s.id = "datascript";
document.body.appendChild(s);
}else{
if (CURRENTSTREAM == ""){
window.setTimeout("reload()",2000);
}else{
callbackf(CURRENTSTREAM);
}
}
},500);
}
Grüße Uwe