Jialx Posted March 6 Share Posted March 6 Hey, I'm trying to create a script filter where I can update the options more than once. What I'm trying to achieve is: Doing a fetch request to get a list of options Show the options Make subsequent fetch requests for each option and as they update reset the options in the dropdown list. "Why?" Because sometimes I don't care what the subsequent fetch requests return and I just want to interact with the options asap. "Why don't you just fetch them all at once?" Thats what I'm doing currently but I'm trying to improve the time to interactive. (I don't care about unhandled requests) Minimal reproducible example: const fetchItems = () => { // except and actual fetch return [ {id: 0, title: 'Something', arg: ''}, {id: 1, title: 'Another thing', arg: ''}, ] } const fetchItemData = (id) => { // except and actual fetch return {id, description: `The status of item ${id}`} } const main = () => { const items = fetchItems() return JSON.stringify({ items }) if (items) { items.forEach((option, index) => { const status = fetchItemData(option.id) items[index].subtitle = status.description JSON.stringify({ items }) // I want to update the items }) } } main() This would be using actual fetches and promise.all in reality but the issue I have is that you can only return once obvs. If there isn't a way to achieve this consider it a feature request to have some kind of setOptions global 🤷 Link to comment
vitor Posted March 6 Share Posted March 6 Fetch one result at a time and use the rerun key from the JSON to rerun the code. Keep track of what you have using environment variables, which you can set and read back. There is an example workflow with a counter which you can access from the + in the workflows list. Jialx 1 Link to comment
Jialx Posted March 6 Author Share Posted March 6 I couldn't easily find which template you where referring too but I understood what to do now to achieve what I want using the rerun api. I created this template file to make it easy for anyone else who stumbles across this using the right keywords haha Create a script filter with language `/bin/zsh` Define the script within as follows: #!/usr/bin/env node node script.js In the workflow directory for example: /Users/Yourname/Library/Application Support/Alfred/Alfred.alfredpreferences/workflows/user.workflow.A07C7F21-... create your script.js file and put this into it: const fs = require('fs') // A mocked fetch request const waitFor = (ms) => new Promise((resolve) => setTimeout(() => resolve("Some cool stuff"), ms)) // Do what you have to do and simply mutate state directly const stages = [ async (state) => { state.items = [{ title: "hey", subtitle: "Fetching..." }] }, async (state) => { const things = await waitFor(500) state.items = state.items.map(i => ({ ...i, subtitle: things })) } ] // You shouldn't need to worry about anything under this comment but I'm hungry and this isn't a PR so I've probably missed something... const STATE_FILE_PATH = 'state.json' const read = async () => { if (fs.existsSync(STATE_FILE_PATH)) { const data = fs.readFileSync(STATE_FILE_PATH, 'utf8') return JSON.parse(data) } else { const initialState = { stage: 0, items: [], } return initialState } } const write = async (state) => { fs.writeFileSync(STATE_FILE_PATH, JSON.stringify(state)) } ~(async () => { const state = await read() await stages[state.stage]?.(state) const isComplete = state.stage >= stages.length - 1 if (isComplete) { fs.rm(STATE_FILE_PATH, (err) => null) state.rerun = undefined } else { state.rerun = 0.1 state.stage++ } await write(state) /** CAN ONLY BE CALLED ONCE PER STAGE - This is the thing that updates alfred options */ console.log(JSON.stringify(state)) })().catch((err) => console.error(`An error occurred: ${err}`)) Link to comment
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now