Overview of Blocking vs Non-Blocking
In Bnlang, an operation is either blocking or non-blocking:
- Blocking — the program waits in place until the operation finishes. The rest of the script (and the event loop) is paused.
- Non-blocking — the program kicks off the operation, keeps running, and the runtime calls your callback later when the result is ready.
Most stdlib modules ship both styles. As a rule of thumb, the sync variant is named fn() and the async variant is fn_async().
Blocking Example
io.read_file blocks until the whole file is in memory. This is fine for small files or one-off scripts.
import "io" as io;
print("start");
var data = io.read_file("notes.txt"); // blocks here
print("file length:", data.byte_length);
print("end");
Non-Blocking Example
io.read_file_async returns immediately; the callback fires when the read is done. The lines after it keep running in the meantime.
import "io" as io;
print("start");
io.read_file_async("notes.txt", function (err, data) {
if (err != null) { print("read failed:", err); return; }
print("file length:", data.byte_length);
});
print("scheduled, doing other work");
Streaming Large Files
For very large files, neither read_file nor read_file_async is the right choice — both load the whole thing into memory.
Use io.open_read to get a stream you can pull from in chunks. The callback receives chunk = null to signal EOF.
import "io" as io;
var src = io.open_read("big.log");
function on_chunk(err, chunk) {
if (err != null) { print("read err:", err); return; }
if (chunk == null) {
print("done");
src.close();
return;
}
print("got", chunk.byte_length, "bytes");
src.read(64 * 1024, on_chunk);
}
src.read(64 * 1024, on_chunk);
Why Non-Blocking Matters
- Keeps a web server, GUI, or CLI responsive while I/O is in flight.
- Lets multiple slow operations (network calls, DB queries, file ops) make progress at the same time.
- Avoids head-of-line blocking when one slow request would otherwise hold up everyone else.
Best Practices
- Default to the async variant in long-running programs (servers, daemons).
- Reach for the sync variant in scripts, build steps, or REPL exploration where simplicity beats throughput.
- Don't mix heavy CPU work into your async callbacks — they share the event-loop thread with every other request.