Search code examples
reactjstypescripttry-catches6-promiserecoiljs

why the try..catch state in recoil selectorFamily catch promise object?


i'm using recoil selectorFamily witch subscribes several selector or selectorFamily for data query. and also using the try...catch for tracking each data query's status. and then i figured out that CATCH state catch the promise object on default excution. so it makes the function calling dataQuery consider it exception but there is no exception. i wonder why this happend.

and also how can i sure if promiseState loged on browser is fulfilled or pending? i'm confusing cause it's marked <pending> but it's promiseState property saying 'fulfilled'.

here is code and browser log as result

const dataQueryForPage = selectorFamily<{data:IPageData; message:string|null;status:number},number>({
key:'dataQueryForPage',
get:(refreshKey)=> async({get})=>{

try{

const data1 = await get(data1Query);
const data2 = await get(data2Query);
const data3 = await get(data3Query);

...


}catch(error){

 console.log('---------------------------------error', error);

        if (error instanceof Promise) {
        
          error
            .then(() => {
              console.log('--------------------------------its resolved');
            })
            .catch(() => {
              console.log('-------------------------------its rejected');
        
            });
...

        }
})

enter image description here


Solution

  • Why are Promises caught?

    The get function provided by the parameters of selector callback throws them.

    If get receives a pending atom, it throws a Promise to interrupt the evaluation. The evaluation will be restarted when the thrown Promise is resolved.

    Source code: https://github.com/facebookexperimental/Recoil/blob/main/packages/recoil/recoil_values/Recoil_selector.js#L724

    And get does NOT return a Promise but the awaited value. So it's not necessary to put an await before get(data1Query)

    Inconsistent PromiseState

    The console evaluates lazily.

    In your case, each state was evaluated twice. The first time was the Promise being logged to console. The second time was you expanded the properties.

    The displayed value corresponded to the state at that very moment.