Big shoutout to tricot's exceptional solution, which resolved all of my queries. I am now taking the opportunity to craft a comprehensive response to my question based on the provided answer.
To begin with, it is crucial to note that onSnapshot
invokes the callback function asynchronously. To replicate this behavior within my own function func_a
, adjustments must be made to my initial code snippet as illustrated below:
function func_a(callback:(arg:string)=>void){
setTimeout(
callback.bind(null,"callback argument"),
1000
)
return "func_a result"
}
To capture both the callback argument and the function return value outside the function, the following code can achieve that purpose:
type CallbackArgumentAndFunctionResult={
callback_argument:string,
function_result:string
}
new Promise<CallbackArgumentAndFunctionResult>(
(resolve)=>{
const function_return=func_a(
(arg)=>resolve({
callback_argument:arg,
function_result:function_return
})
)
}
).then((arg_res)=>{
console.log(arg_res.callback_argument)
console.log(arg_res.function_result)
})
With the execution of the callback function being asynchronous post function value return, accessing the return value inside the callback enables simultaneous retrieval of both values, thereby serving as the foundation for compiling the aforementioned code.
This methodology empowers me to emulate the intended functionality of onSnapshot
. For instance, in a React setting, I can segregate the unsubscribe
function and snapshot
from onSnapshot
, demonstrated as follows:
export default function Home(){
const [myUnsubscribe,setMyUnsubscribe]=useState<Unsubscribe|undefined>()
const ObtainCity=()=>new Promise<SnapshotUnsubscribe>((resolve)=>{
const unsubscribe = onSnapshot(
doc(db, "cities", "SF"),
(snapshot)=>resolve({ snapshot, unsubscribe })
)
})
useEffect(
()=>{
ObtainCity().then(({snapshot, unsubscribe})=>{
setMyUnsubscribe(unsubscribe)
})
return ()=>{myUnsubscribe && myUnsubscribe()}
},[]
)
return <div></div>
}
Furthermore, a resolution to my query regarding the initial code example where the callback function precedes the return value is elaborated upon:
As the function returns the value subsequent to executing the callback function, immediate resolution within the callback function would fail to assign the return value. Hence, the following code emphasizes introducing an asynchronous delay in the callback function prior to resolving:
function func_a(callback:(arg:string)=>void){
callback("callback argument")
return "func_a result"
}
type CallbackArgumentAndFunctionResult={
callback_argument:string,
function_result:string
}
new Promise<CallbackArgumentAndFunctionResult>(
(resolve)=>{
const function_return=func_a((arg)=>{
setTimeout(
()=>{
resolve({
callback_argument:arg,
function_result:function_return
})
},
1000)
})
}
).then((arg_res)=>{
console.log(arg_res.callback_argument)
console.log(arg_res.function_result)
})