Start · Sprachen · JavaScript · Referenz · NDEFReader: reading

NDEFReader: reading

Ereignis

Wird ausgelöst, sobald ein NDEF-fähiges NFC-Tag in Reichweite kommt und seine Daten als <code>NDEFReadingEvent</code> gelesen werden können.

seit JavaScript Experimentell: nur Chrome für Android 89+ Kategorie: webapi

Signatur

ndefReader.addEventListener("reading", handler)

Beschreibung

Das reading-Ereignis der Schnittstelle NDEFReader wird jedes Mal ausgelöst, wenn ein kompatibles NFC-Gerät (z. B. ein NDEF-Tag oder ein anderes Smartphone) in den Lesebereich des Geräts gebracht wird und eine neue NDEF-Nachricht vorliegt. Voraussetzung ist, dass vorher NDEFReader.prototype.scan() aufgerufen und die Berechtigung erteilt wurde.

Der Handler erhält ein NDEFReadingEvent mit zwei wichtigen Eigenschaften: serialNumber (die Seriennummer des Tags als hexadezimaler String, z. B. "04:a2:3b:…") und message (ein NDEFMessage-Objekt mit einem Array records aus NDEFRecord-Einträgen). Jeder Datensatz hat einen recordType (z. B. "text", "url", "mime"), optional mediaType, encoding, lang sowie die eigentlichen Nutzdaten in data als DataView.

Man kann den Handler per addEventListener("reading", handler) oder über die Eigenschaft ndefReader.onreading = handler registrieren. Typische Einsatzzwecke sind Inventarverwaltung, Check-in-Systeme, Museumsführer oder das Auslesen von URLs und Texten aus Tags. Fehlerhafte oder nicht lesbare Tags lösen statt reading das Ereignis readingerror aus.

Parameter

Name Typ Default Beschreibung
$type Pflicht string Der Ereignisname "reading".
$handler Pflicht (event: NDEFReadingEvent) => void Callback, der bei jedem gelesenen Tag aufgerufen wird. Erhält ein NDEFReadingEvent mit serialNumber und message.
$options boolean|AddEventListenerOptions false Optionale Listener-Optionen wie once oder signal (zum Entfernen per AbortController).

Rückgabewert

Typ
void
Beschreibung
addEventListener gibt nichts zurück. Die Daten stehen im übergebenen NDEFReadingEvent zur Verfügung.

Beispiele

Tags scannen und Text-/URL-Datensätze ausgeben

const startScan = async () => {
  if (!('NDEFReader' in window)) {
    console.log('Web NFC wird nicht unterstützt.');
    return;
  }
  const reader = new NDEFReader();
  await reader.scan(); // muss durch Nutzergeste ausgelöst werden

  reader.addEventListener('reading', ({ serialNumber, message }) => {
    console.log(`Tag erkannt: ${serialNumber}`);
    for (const record of message.records) {
      if (record.recordType === 'text') {
        const decoder = new TextDecoder(record.encoding ?? 'utf-8');
        console.log(`Text (${record.lang}): ${decoder.decode(record.data)}`);
      } else if (record.recordType === 'url') {
        console.log(`URL: ${new TextDecoder().decode(record.data)}`);
      } else {
        console.log(`Anderer Typ: ${record.recordType}`);
      }
    }
  });

  reader.addEventListener('readingerror', () => {
    console.log('Tag konnte nicht gelesen werden.');
  });
};

document.querySelector('#scan').addEventListener('click', startScan);
Tag erkannt: 04:a2:3b:5c:6d:70:80 Text (de): Hallo Welt

on-Property und Beenden des Scans per AbortController

const controller = new AbortController();
const reader = new NDEFReader();

document.querySelector('#scan').addEventListener('click', async () => {
  try {
    await reader.scan({ signal: controller.signal });
    reader.onreading = (event) => {
      console.log('Seriennummer:', event.serialNumber);
      console.log('Anzahl Datensätze:', event.message.records.length);
    };
  } catch (err) {
    console.log(`Scan fehlgeschlagen: ${err.name}`);
  }
});

document.querySelector('#stop').addEventListener('click', () => {
  controller.abort(); // beendet den Scan, keine weiteren reading-Events
  reader.onreading = null;
});
Seriennummer: 04:a2:3b:5c:6d:70:80 Anzahl Datensätze: 1

Nur ein einziges Tag lesen (once) und JSON-MIME-Daten auswerten

const readOnce = async () => {
  const reader = new NDEFReader();
  const controller = new AbortController();
  await reader.scan({ signal: controller.signal });

  return new Promise((resolve) => {
    reader.addEventListener('reading', ({ message }) => {
      const record = message.records.find(
        (r) => r.recordType === 'mime' && r.mediaType === 'application/json'
      );
      controller.abort();
      resolve(record ? JSON.parse(new TextDecoder().decode(record.data)) : null);
    }, { once: true });
  });
};

document.querySelector('#scan').addEventListener('click', async () => {
  const data = await readOnce();
  console.log(data);
});
{ artikel: "A-1042", lager: "B3" }

// Wichtig · Fallstricke

  • Kompatibilität: Web NFC ist experimentell und derzeit nur in Chrome für Android (ab Version 89) verfügbar. Desktop-Browser, Firefox und Safari/iOS unterstützen die API nicht – immer per 'NDEFReader' in window prüfen.
  • Sicherer Kontext & Nutzergeste: Die API funktioniert nur über HTTPS, nur im obersten Browsing-Kontext (nicht in iframes) und scan() muss beim ersten Mal durch eine Nutzeraktion (z. B. Klick) ausgelöst werden, sonst wird ein NotAllowedError geworfen.
  • Listener vor dem Tag registrieren: Wird ein Tag gelesen, bevor ein reading-Handler existiert, geht das Ereignis verloren. Handler am besten direkt nach (oder vor) dem Aufruf von scan() setzen.
  • Die Ereignisse feuern nur, solange die Seite sichtbar ist und der Bildschirm entsperrt ist; beim Wechsel in den Hintergrund wird das Scannen pausiert.
  • Das Ereignis kann bei gleichem Tag mehrfach feuern, wenn es erneut angenähert wird – ggf. per serialNumber entprellen.
  • Sicherheit: Tag-Inhalte sind nicht vertrauenswürdige Eingaben. Gelesene Texte/URLs niemals ungeprüft per innerHTML einfügen oder automatisch aufrufen (XSS, Phishing). Die serialNumber ist nicht fälschungssicher und taugt nicht zur Authentifizierung.
  • Fehlerhafte Tags lösen readingerror statt reading aus – diesen Fall immer mitbehandeln.