Last active
February 2, 2022 23:07
-
-
Save boukeversteegh/3de2d12f6c1a3f5a5ef4d428cbd9a163 to your computer and use it in GitHub Desktop.
Async getters for vue
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<template> | |
<input v-model="query"/> | |
<ul> | |
<li v-for="user in users" :key="user.name">{{ user.name }}</li> | |
</ul> | |
</template> | |
<script lang="ts"> | |
@Component({}) | |
export default class ExampleComponent extends Vue { | |
query = 'john' | |
@Async({ default: [] }) | |
get users(): {name: string}[] { | |
// You can call async functions within your getters, by decorating the getter with @Async() | |
return async(searchAsync(this.query, true)) | |
} | |
get userCount() { | |
// The async property is useable, as if it was a normal property. | |
return this.users.length | |
} | |
@Async() | |
get exampleWithAwait() { | |
return async(async () => { | |
var message = await this.someMessageAsync(); | |
return message.length; | |
}); | |
} | |
async someMessageAsync() { | |
return "Hello world"; | |
} | |
} | |
</script> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Some fake data and fake async endpoint | |
const userData = [ | |
{ | |
name: 'John Doe', | |
email: '[email protected]', | |
}, | |
{ | |
name: 'Jane Doe', | |
email: '[email protected]', | |
}, | |
] | |
export function searchAsync(query: string, caseSensitive: boolean): Promise<User[]> { | |
return new Promise((resolve) => { | |
setTimeout(() => { | |
resolve( | |
userData.filter((user) => user.name.toLowerCase().indexOf(query?.toLowerCase()) > -1) | |
) | |
}, 500) | |
}) | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* VueJS calculated properties that return a Promise | |
*/ | |
// @Async() decorator | |
export function Async(asyncOptions: { default: any }) { | |
return createDecorator((options, property) => { | |
// Define a new reactive property on the Vue instance | |
options.data = () => ({ [property]: asyncOptions?.default }) | |
// Move the async property to *Async | |
const asyncProperty = `${property}Async` | |
options.computed[asyncProperty] = options.computed[property] | |
// Watch changes to the async property | |
options.watch = { | |
[asyncProperty]: { | |
immediate: true, | |
handler: function (val, oldVal) { | |
// The promise changed, so listen to it. | |
val.then((value) => { | |
// Write the value to the reactive property | |
console.log('resolved', value) | |
this[property] = value | |
return value | |
}) | |
}, | |
}, | |
} | |
/* eslint-disable fp/no-delete */ | |
delete options.computed[property] | |
}) | |
} | |
// async helper method | |
export function asyncComputed<T>(promise: Promise<T> | (() => Promise<T>)): T { | |
return (typeof promise === 'function' ? promise() : promise) as any | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment