Skip to content

Commit 0b9dc7a

Browse files
zolkiskenchris
andcommitted
Remove ignoreRead and add info on how to implement manually (#571) (#599)
* Remove ignoreRead and add info on how to implement manually Co-authored-by: Kenneth Rohde Christiansen <[email protected]>
1 parent 8dd4f22 commit 0b9dc7a

File tree

1 file changed

+170
-38
lines changed

1 file changed

+170
-38
lines changed

index.html

Lines changed: 170 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -990,6 +990,37 @@ <h4>
990990
</pre>
991991
</section>
992992

993+
<section><h3>General information about writing data</h3>
994+
<p>
995+
Writing data is generally straightforward, but there are a few
996+
gotcha's around how writing works with NFC.
997+
</p>
998+
<p>
999+
An NFC reader works by polling, so in order to be able to
1000+
write to a tag, a tag first needs to be found and read, which
1001+
means that polling needs to be initialized first.
1002+
</p>
1003+
<p>
1004+
If polling is not initiated already by first calling `scan()`,
1005+
then the `write()` method will initiate it temporarily until a
1006+
tag was found and read, and writing to it was attempted.
1007+
</p>
1008+
<p>
1009+
This means that the flow is that first a read it performed
1010+
as the tag is first found, then followed by a write.
1011+
</p>
1012+
<p>
1013+
This means that if `scan()` is running and you have an event
1014+
listener for the `reading` event, it will be dispatched once
1015+
during a `write()` operation, which might not be the intended
1016+
behavior.
1017+
</p>
1018+
<p>
1019+
In the following sections we will discuss how you can easily
1020+
deal with this behavior, but first a few simple examples.
1021+
</p>
1022+
</section>
1023+
9931024
<section><h3>Write a text string</h3>
9941025
<p>
9951026
Writing a text string to an NFC tag is straightforward.
@@ -1008,20 +1039,101 @@ <h4>
10081039

10091040
<section> <h3>Write a URL</h3>
10101041
<p>
1011-
In order to write an NDEF record of URL type, simply use NDEFMessage.
1042+
In order to write an NDEF record of URL type, simply use NDEFMessage. Here
1043+
we rely on async/await.
10121044
</p>
10131045
<pre class="example">
1014-
const writer = new NDEFWriter();
1015-
writer.write({
1016-
records: [{ recordType: "url", data: "https://w3c.github.io/web-nfc/" }]
1017-
}).then(() => {
1018-
console.log("Message written.");
1019-
}).catch(_ => {
1046+
const ndef = new NDEFReader();
1047+
try {
1048+
ndef.write({
1049+
records: [{ recordType: "url", data: "https://w3c.github.io/web-nfc/" }]
1050+
});
1051+
} catch {
10201052
console.log("Write failed :-( try again.");
1021-
});
1053+
};
10221054
</pre>
10231055
</section>
10241056

1057+
<section> <h3>Handling initial reads while writing</h3>
1058+
<p>
1059+
In order to write, a tag needs to be found and thus read. This gives
1060+
you the ability to check whether it is actually a tag that you want to
1061+
write to or not, by checking existing data or serial number.
1062+
</p>
1063+
<p>
1064+
For this reason, it is recommended calling `write()` from a `reading`
1065+
event.
1066+
</p>
1067+
The below example shows how to coordinate between a common `reading`
1068+
handler and one used specifically for a single write.
1069+
</p>
1070+
<pre class="example">
1071+
const reader = new NDEFReader();
1072+
let ignoreRead = false;
1073+
1074+
reader.onreading(event => {
1075+
if (ignoreRead) {
1076+
return; // write pending, ignore read.
1077+
}
1078+
1079+
console.log("We read a tag, but not during pending write!");
1080+
}
1081+
1082+
function write(data) {
1083+
ignoreRead = true;
1084+
return new Promise((resolve, reject) => {
1085+
reader.addEventListener("reading", event => {
1086+
// Check if we want to write to this tag, or reject.
1087+
reader.write(data).then(resolve, reject).finally(() => ignoreRead = false);
1088+
}, { once: true });
1089+
});
1090+
}
1091+
1092+
await reader.scan();
1093+
try {
1094+
await write("Hello World");
1095+
console.log("We wrote to a tag!")
1096+
} catch(err) {
1097+
console.error("Something went wrong", err);
1098+
}
1099+
</pre>
1100+
</section>
1101+
1102+
<section> <h3>Scheduling a write with a timeout</h3>
1103+
<p>
1104+
It can sometime be useful to set a time limit on a write operation.
1105+
Like you ask the user to touch a tag, and if no tag is found within
1106+
a certain amount of time, then you time out.
1107+
</p>
1108+
<pre class="example">
1109+
const reader = new NDEFReader();
1110+
reader.onreading(event => console.log("We read a tag!"));
1111+
1112+
function write(data, { timeout } = {}) {
1113+
return new Promise((resolve, reject) => {
1114+
const ctlr = new AbortController();
1115+
ctlr.signal.onabort = _ => reject("Time is up, bailing out!");
1116+
if (typeof timeout == "number") {
1117+
setTimeout(() => ctlr.abort(), timeout);
1118+
}
1119+
1120+
reader.addEventListener("reading", event => {
1121+
reader.write(data, { signal: ctlr.signal }).then(resolve, reject);
1122+
}, { once: true });
1123+
});
1124+
}
1125+
1126+
await reader.scan();
1127+
try {
1128+
// Let's wait for 5 seconds only.
1129+
write("Hello World", { timeout: 5_000 });}
1130+
} catch(err) {
1131+
console.error("Something went wrong", err);
1132+
} finally {
1133+
console.log("We wrote to a tag!");
1134+
}
1135+
</pre>
1136+
</section>
10251137

10261138
<section> <h3>Handle scanning errors</h3>
10271139
<p>
@@ -1044,6 +1156,37 @@ <h4>
10441156
</pre>
10451157
</section>
10461158

1159+
<section> <h3>Read a single tag, once</h3>
1160+
<p>
1161+
This example show you how to easily create a convenience function
1162+
that just reads a single tag and then stops polling, saving
1163+
battery life by cutting unneeded work.
1164+
</p>
1165+
<p>
1166+
The example could easily be extended to time out after a given
1167+
amount of milliseconds.
1168+
</p>
1169+
<pre class="example">
1170+
const reader = new NDEFReader();
1171+
1172+
function read() {
1173+
return new Promise((resolve, reject) => {
1174+
const ctlr = new AbortController();
1175+
ctlr.signal.onabort = reject;
1176+
reader.addEventListener("reading", event => {
1177+
ctlr.abort();
1178+
resolve(event);
1179+
}, { once: true });
1180+
reader.scan({ signal: ctlr.signal }).catch(err => reject(err));
1181+
});
1182+
}
1183+
1184+
read().then(({ serialNumber }) => {
1185+
console.log(serialNumber);
1186+
})
1187+
</pre>
1188+
</section>
1189+
10471190
<section> <h3>Read data from tag, and write to empty ones</h3>
10481191
<p>
10491192
This example shows reading various different kinds of data which can be
@@ -1180,29 +1323,27 @@ <h4>
11801323

11811324
<section> <h3>Write data and print out existing data</h3>
11821325
<p>
1183-
Writing data requires tapping an <a>NFC tag</a>. If data should be
1184-
read during the same tap, we need to set the {{NDEFWriteOptions/ignoreRead}}
1185-
property to `false`.
1326+
Writing data requires tapping an <a>NFC tag</a>.
11861327
</p>
11871328
<pre class="example">
1188-
const reader = new NDEFReader();
1189-
reader.scan().then(() => {
1329+
const ndef = new NDEFReader();
11901330

1191-
reader.onreading = event => {
1192-
const decoder = new TextDecoder();
1193-
for (const record of event.message.records) {
1194-
console.log("Record type: " + record.recordType);
1195-
console.log("MIME type: " + record.mediaType);
1196-
console.log("=== data ===\n" + decoder.decode(record.data));
1197-
}
1198-
};
1331+
ndef.onreading = async event => {
1332+
const decoder = new TextDecoder();
1333+
for (const record of event.message.records) {
1334+
console.log("Record type: " + record.recordType);
1335+
console.log("MIME type: " + record.mediaType);
1336+
console.log("=== data ===\n" + decoder.decode(record.data));
1337+
}
11991338

1200-
const writer = new NDEFWriter();
1201-
return writer.write("Writing data is fun!", { ignoreRead: false });
1339+
try {
1340+
await ndef.write("Overriding data is fun!");
1341+
} catch(error) {
1342+
console.log(`Write failed :-( try again: ${error}.`);
1343+
}
1344+
};
12021345

1203-
}).catch(error => {
1204-
console.log(`Write failed :-( try again: ${error}.`);
1205-
});
1346+
ndef.scan();
12061347
</pre>
12071348
</section>
12081349

@@ -1224,7 +1365,7 @@ <h4>
12241365
};
12251366

12261367
// Stop listening to NDEF messages after 3s.
1227-
setTimeout(() => controller.abort(), 3000);
1368+
setTimeout(() => controller.abort(), 3_000);
12281369
</pre>
12291370
</section>
12301371

@@ -2203,21 +2344,15 @@ <h2>The <dfn>record type</dfn> string</h2>
22032344
<h3>The <dfn>NDEFWriteOptions</dfn> dictionary</h3>
22042345
<pre class="idl">
22052346
dictionary NDEFWriteOptions {
2206-
boolean ignoreRead = true;
22072347
boolean overwrite = true;
22082348
AbortSignal? signal;
22092349
};
22102350
</pre>
2211-
<p>
2212-
When the value of the <dfn>ignoreRead</dfn> property is `true`, the
2213-
<a>NFC reading algorithm</a> will skip reading <a>NFC tag</a>s for the
2214-
<a>activated reader objects</a>.
2215-
</p>
22162351
<p>
22172352
When the value of the <dfn>overwrite</dfn> property is
22182353
`false`, the <a href="#steps-write">write algorithm</a>
2219-
will read the <a>NFC tag</a> regardless of the `ignoreRead` value
2220-
to determine if it has <a>NDEF</a> records on it, and if yes, it will not
2354+
will read the <a>NFC tag</a> to determine if it has
2355+
<a>NDEF</a> records on it, and if yes, it will not
22212356
execute any pending write.
22222357
</p>
22232358
<p>
@@ -3512,9 +3647,6 @@ <h3><dfn>Writing content</dfn></h3>
35123647
<li>
35133648
If <a>NFC is suspended</a>, abort these steps.
35143649
</li>
3515-
<li>
3516-
If there is a <a>pending write tuple</a> and its writer's option's ignoreRead is `true`, abort these steps.
3517-
</li>
35183650
<li>
35193651
If the <a>NFC tag</a> in proximity range does not expose <a>NDEF</a>
35203652
technology for reading or formatting, run the following sub-steps:

0 commit comments

Comments
 (0)