Last active
May 2, 2024 07:23
-
-
Save ZouYouShun/1600af64d13728f3775dd728d6ad1460 to your computer and use it in GitHub Desktop.
createExternalExecController
This file contains hidden or 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
import { | |
filter, | |
firstValueFrom, | |
fromEvent, | |
map, | |
merge, | |
share, | |
tap, | |
timer, | |
} from 'rxjs'; | |
/** | |
* Creates an external execution controller. | |
* | |
* @example | |
* ```tsx | |
* const execController = createExternalExecController("my-channel", (value) => { | |
* console.log(value); | |
* }); | |
* | |
* execController.isExist().then((isExist) => { | |
* if (!isExist) { | |
* execController.exec("Hello, world!"); // will exec in external window that receive the message | |
* } | |
* }); | |
* ``` | |
* | |
* @param channelName - The name of the broadcast channel. | |
* @param exec - A function that handles the execution of a value. | |
* @returns An object with methods and properties related to the external execution controller. | |
*/ | |
export function createExternalExecController( | |
channelName: string, | |
exec: (value: string | object) => void, | |
) { | |
const channel = new BroadcastChannel(channelName); | |
const events = { | |
exec: 'exec', | |
isExist: 'isExist', | |
isExistResponse: 'isExistResponse', | |
}; | |
const obs = fromEvent< | |
MessageEvent<{ type: keyof typeof events; value: string | object }> | |
>(channel, 'message').pipe( | |
map((event) => event.data), | |
tap(({ type, value }) => { | |
switch (type) { | |
case 'isExist': | |
channel.postMessage({ type: events.isExistResponse }); | |
break; | |
case 'exec': | |
exec(value); | |
break; | |
default: | |
break; | |
} | |
}), | |
share(), | |
); | |
obs.subscribe(); | |
return { | |
channel, | |
events, | |
exec: (value?: string | object) => { | |
channel.postMessage({ type: events.exec, value }); | |
}, | |
isExist: async () => { | |
channel.postMessage({ type: events.isExist }); | |
const result = await firstValueFrom( | |
merge( | |
timer(1000).pipe(map(() => false)), | |
obs.pipe( | |
filter((x) => x.type === events.isExistResponse), | |
map(() => true), | |
), | |
), | |
); | |
return result; | |
}, | |
}; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment