@@ -235,11 +235,56 @@ def get_uid_str(uid):
235235 let pluginFileTypes = [];
236236 let pluginJointFileTypes = [];
237237
238+ let pending = [];
239+ let batchId = 0;
240+
241+ async function processBatch(prevPendingArr) {
242+ const [dataArr, buffersArr] = await view.experimental.invoke("_zarr_get_multi", prevPendingArr.map(d => d.params), {
243+ signal: AbortSignal.timeout(invokeTimeout),
244+ });
245+ prevPendingArr.forEach((prevPendingItem, i) => {
246+ const data = dataArr[i];
247+ const bufferData = buffersArr[i];
248+ const { params, resolve, reject } = prevPendingItem;
249+ const [storeUrl, key] = params;
250+
251+ if (!data.success) {
252+ resolve(undefined);
253+ }
254+
255+ if (key.includes("spatialdata_attrs") && key.endsWith("0") && !ArrayBuffer.isView(bufferData.buffer)) {
256+ // For some reason, the Zarrita.js UnicodeStringArray does not seem to work with
257+ // ArrayBuffers (throws a TypeError), so here we convert to Uint8Array if needed.
258+ // This error is occurring specifically for the arr.getChunk call within the AnnDataSource._loadString function.
259+ // TODO: figure out a more long-term solution.
260+ resolve(new Uint8Array(bufferData.buffer));
261+ }
262+
263+ resolve(bufferData.buffer);
264+ });
265+ }
266+
267+ function run() {
268+ processBatch(pending);
269+ pending = [];
270+ batchId = 0;
271+ }
272+
273+ function enqueue(params) {
274+ batchId = batchId || requestAnimationFrame(() => run());
275+ let { promise, resolve, reject } = Promise.withResolvers();
276+ pending.push({ params, resolve, reject });
277+ return promise;
278+ }
279+
280+
238281 const stores = Object.fromEntries(
239282 storeUrls.map(storeUrl => ([
240283 storeUrl,
241284 {
242285 async get(key) {
286+ return enqueue([storeUrl, key]);
287+ /*
243288 const [data, buffers] = await view.experimental.invoke("_zarr_get", [storeUrl, key], {
244289 signal: AbortSignal.timeout(invokeTimeout),
245290 });
@@ -254,6 +299,7 @@ def get_uid_str(uid):
254299 }
255300
256301 return buffers[0].buffer;
302+ */
257303 },
258304 }
259305 ])),
@@ -576,6 +622,22 @@ def _zarr_get(self, params, buffers):
576622 except KeyError :
577623 buffers = []
578624 return {"success" : len (buffers ) == 1 }, buffers
625+
626+ @anywidget .experimental .command
627+ def _zarr_get_multi (self , params_arr , buffers ):
628+ # This variant of _zarr_get supports batching.
629+ result_dicts = []
630+ result_buffers = []
631+ for params in params_arr :
632+ [store_url , key ] = params
633+ store = self ._stores [store_url ]
634+ try :
635+ result_buffers .append (store [key .lstrip ("/" )])
636+ result_dicts .append ({ "success" : True })
637+ except KeyError :
638+ result_buffers .append (b'' )
639+ result_dicts .append ({ "success" : False })
640+ return result_dicts , result_buffers
579641
580642 @anywidget .experimental .command
581643 def _plugin_command (self , params , buffers ):
0 commit comments