fix(#2443): address asyncBtn review notes
- asyncBtn now returns fn().finally(...) so callers can await/chain it - Move re-fetch calls inside try/catch in core.js and permissions.js so network errors from fetchAndRenderStalePerms / fetchAndRender* are caught instead of escaping as unhandled rejections - clearStaleAgent returns the asyncBtn promise so the function is properly awaitable when a button is present - Update asyncBtn doc comment to reflect the return-value contract
This commit is contained in:
parent
bd7ae83860
commit
1acc271108
3 changed files with 11 additions and 10 deletions
|
|
@ -115,12 +115,11 @@ function renderStalePerms(root, ghosts) {
|
||||||
errP.hidden = false;
|
errP.hidden = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
await fetchAndRenderStalePerms();
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
errP.textContent = 'failed to clear perms for ' + name + ': ' + err;
|
errP.textContent = 'failed to clear perms for ' + name + ': ' + err;
|
||||||
errP.hidden = false;
|
errP.hidden = false;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
await fetchAndRenderStalePerms();
|
|
||||||
}));
|
}));
|
||||||
li.append(btn);
|
li.append(btn);
|
||||||
ul.append(li);
|
ul.append(li);
|
||||||
|
|
|
||||||
|
|
@ -337,17 +337,17 @@ async function clearStaleAgent(name, sectionRoot) {
|
||||||
setSaveNote('failed to remove ' + name + ': ' + text, true);
|
setSaveNote('failed to remove ' + name + ': ' + text, true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
// Re-fetch both sections so the stale row disappears.
|
||||||
|
await Promise.all([fetchAndRenderCapabilities(), fetchAndRenderToolGroups()]);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
setSaveNote('failed to remove ' + name + ': ' + err, true);
|
setSaveNote('failed to remove ' + name + ': ' + err, true);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
// Re-fetch both sections so the stale row disappears.
|
|
||||||
await Promise.all([fetchAndRenderCapabilities(), fetchAndRenderToolGroups()]);
|
|
||||||
};
|
};
|
||||||
// asyncBtn guards double-submit; fall through without guard when there
|
// asyncBtn guards double-submit; fall through without guard when there
|
||||||
// is no button (e.g. called programmatically without a DOM context).
|
// is no button (e.g. called programmatically without a DOM context).
|
||||||
if (btn) asyncBtn(btn, doDelete);
|
// Return the promise so callers can await clearStaleAgent() if needed.
|
||||||
else await doDelete();
|
if (btn) return asyncBtn(btn, doDelete);
|
||||||
|
await doDelete();
|
||||||
}
|
}
|
||||||
|
|
||||||
function clearSaveStatus() {
|
function clearSaveStatus() {
|
||||||
|
|
|
||||||
|
|
@ -20,14 +20,16 @@
|
||||||
// Error handling: `asyncBtn` restores the button on any thrown error /
|
// Error handling: `asyncBtn` restores the button on any thrown error /
|
||||||
// rejected promise but does NOT surface the error — callers must catch
|
// rejected promise but does NOT surface the error — callers must catch
|
||||||
// and display it themselves (via `themedToast`, `alert`, a status span,
|
// and display it themselves (via `themedToast`, `alert`, a status span,
|
||||||
// etc.) before the re-throw, or handle it inside `fn` without
|
// etc.) inside `fn` without re-throwing. `fn` must not let errors escape
|
||||||
// re-throwing.
|
// unhandled: `asyncBtn` returns the `fn().finally(...)` promise so
|
||||||
|
// callers can optionally chain `.catch` or `await`, but does not add its
|
||||||
|
// own catch — an unhandled rejection from `fn` will propagate normally.
|
||||||
export function asyncBtn(btn, fn) {
|
export function asyncBtn(btn, fn) {
|
||||||
if (btn.disabled) return; // double-click guard
|
if (btn.disabled) return; // double-click guard
|
||||||
const orig = btn.innerHTML;
|
const orig = btn.innerHTML;
|
||||||
btn.disabled = true;
|
btn.disabled = true;
|
||||||
btn.innerHTML = '<span class="spinner">◐</span>';
|
btn.innerHTML = '<span class="spinner">◐</span>';
|
||||||
fn().finally(() => {
|
return fn().finally(() => {
|
||||||
btn.disabled = false;
|
btn.disabled = false;
|
||||||
btn.innerHTML = orig;
|
btn.innerHTML = orig;
|
||||||
});
|
});
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue