Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added plain html example #1635

Merged
merged 1 commit into from
Mar 4, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 51 additions & 0 deletions examples/plain-html/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<script>
const getDb = async () => {
const duckdb = window.duckdbduckdbWasm;
// @ts-ignore
if (window._db) return window._db;
const JSDELIVR_BUNDLES = duckdb.getJsDelivrBundles();

// Select a bundle based on browser checks
const bundle = await duckdb.selectBundle(JSDELIVR_BUNDLES);

const worker_url = URL.createObjectURL(
new Blob([`importScripts("${bundle.mainWorker}");`], {
type: "text/javascript",
})
);

// Instantiate the asynchronus version of DuckDB-wasm
const worker = new Worker(worker_url);
// const logger = null //new duckdb.ConsoleLogger();
const logger = new duckdb.ConsoleLogger();
const db = new duckdb.AsyncDuckDB(logger, worker);
await db.instantiate(bundle.mainModule, bundle.pthreadWorker);
URL.revokeObjectURL(worker_url);
window._db = db;
return db;
};
</script>
<script type="module">
import * as duckdbduckdbWasm from "https://cdn.jsdelivr.net/npm/@duckdb/[email protected]/+esm";
window.duckdbduckdbWasm = duckdbduckdbWasm;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why is this needed at all? there is a module system, you can use it right away. You also have top-level await in there so I hope this example can be improved. If you need help, I'd be happy to help with such improvement.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A better example that doesn't need to leak globally ... it's just an ECMAScript module, check duckdb-loader.js: https://pyscript.com/@agiammarchi/jolly-silence-copy/latest

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what happens if 2 different files import the same duckdb-loader. would duckdb be initialized twice ? or would the PackageQueryApp be singleton ?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in ESM you can import the same thing dozen times its code will run only once and its exports will be available to any other importer of the same file ... if that's what you are asking. If it's not, your "trashing as global reference" is not a solution, there's not even a check if it was there before, so I am not sure I am following the question or the concern, but nothing is solved better (or at all) in the current state of affairs.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i was not talking about the import. that one is cached.

i am talking about the db connection:
await this.db.connect();

will this need to be recreated all the time ?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it depends ... if you want a single connection create a module that returns always the same connection

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that's actually why i am using window._db in the script, to store the connection. is this equivalent to what you are suggesting? not sure how to store state in a module

Copy link

@WebReflection WebReflection Jul 31, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

import * as duckdbduckdbWasm from "whatever";
let _db;
export default (...args) => _db || (
  _db = duckdbduckdbWasm.connect(...args)
);

you have that module as ./duckdb-singleton.js and you're done?

import duckdbConnection from './duckdb-singleton.js';

const db = duckdbConnection("some", { argu: "ment" });

with a globally shared db with always same parameters you can also just:

import * as duckdbduckdbWasm from "whatever";
export default new duckdbduckdbWasm.connect(...args);

then you just import db from './duckdb-singleton.js' and you're done.

The module system gives you everything you need to have an insternal state ... nothing leaks on the global which was my initial point, and it's cached, as exports, as you know ... code won't get executed more than once neither, unless everyone is re-bundling the thing ... we use sticky-module for that reason, if multiple projects re-bundle stuff, first come first serve, that's the contract.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did update my previous answer expanding on various things, sorry for the extra ping.

getDb().then(async (db) => {
// Create a new connection
const conn = await db.connect();
// Prepare query
const stmt = await conn.prepare(
`SELECT v + ? FROM generate_series(0, 10000) AS t(v);`
);
// ... and run the query with materialized results
console.log((await stmt.query(234)).toArray());
});
</script>
</body>
</html>