@@ -1355,88 +1355,110 @@ export const debounce: {
13551355
13561356/**
13571357 * @since 1.0.0
1358- * @category combinators
1358+ * @category Optimistic
13591359 */
1360- export const withOptimisticSet : {
1361- < A , XA , XE , W = A extends Result . Result < infer _A , infer _E > ? _A : A > (
1360+ export const optimistic = < A > (
1361+ self : Rx < A >
1362+ ) : Writable < A , Rx < Result . Result < A extends Result . Result < infer _A , infer _E > ? _A : A , unknown>>> => {
1363+ let counter = 0
1364+ const writeRx = state (
1365+ [
1366+ counter ,
1367+ undefined as any as Rx < Result . Result < A extends Result . Result < infer _A , infer _E > ? _A : A , unknown > >
1368+ ] as const
1369+ )
1370+ return writable (
1371+ ( get ) => {
1372+ let lastValue = get . once ( self )
1373+ const isResult = Result . isResult ( lastValue )
1374+ get . subscribe ( self , ( value ) => {
1375+ lastValue = value
1376+ if ( ! Result . isResult ( value ) ) {
1377+ return get . setSelf ( value )
1378+ }
1379+ const current = Option . getOrUndefined ( get . self < Result . Result < any , any > > ( ) ) !
1380+ if ( Result . isSuccess ( current ) && Result . isSuccess ( value ) ) {
1381+ if ( value . timestamp >= current . timestamp ) {
1382+ get . setSelf ( value )
1383+ }
1384+ } else {
1385+ get . setSelf ( value )
1386+ }
1387+ } )
1388+ const transitions = new Set < Rx < Result . Result < A extends Result . Result < infer _A , infer _E > ? _A : A , unknown > > > ( )
1389+ const cancels = new Set < ( ) => void > ( )
1390+ get . subscribe ( writeRx , ( [ , rx ] ) => {
1391+ if ( transitions . has ( rx ) ) {
1392+ return
1393+ }
1394+ transitions . add ( rx )
1395+ const cancel = get . registry . subscribe ( rx , ( result ) => {
1396+ if ( Result . isSuccess ( result ) && result . waiting ) {
1397+ return get . setSelf ( isResult ? Result . success ( result . value , { waiting : true } ) : result . value )
1398+ }
1399+ transitions . delete ( rx )
1400+ cancels . delete ( cancel )
1401+ cancel ( )
1402+ if ( transitions . size === 0 ) {
1403+ if ( Result . isFailure ( result ) ) {
1404+ get . setSelf ( lastValue )
1405+ }
1406+ get . refresh ( self )
1407+ }
1408+ } , { immediate : true } )
1409+ cancels . add ( cancel )
1410+ } )
1411+ get . addFinalizer ( ( ) => {
1412+ for ( const cancel of cancels ) {
1413+ cancel ( )
1414+ }
1415+ transitions . clear ( )
1416+ cancels . clear ( )
1417+ } )
1418+ return lastValue
1419+ } ,
1420+ ( ctx , rx ) => ctx . set ( writeRx , [ ++ counter , rx ] ) ,
1421+ ( refresh ) => refresh ( self )
1422+ )
1423+ }
1424+
1425+ /**
1426+ * @since 1.0.0
1427+ * @category Optimistic
1428+ */
1429+ export const optimisticFn : {
1430+ < A , W , XA , XE , OW = A extends Result . Result < infer _A , infer _E > ? _A : A > (
13621431 options : {
1363- readonly updateToValue : (
1364- value : W ,
1365- current : NoInfer < A >
1366- ) => A extends Result . Result < infer _A , infer _E > ? _A : NoInfer < A >
1367- readonly fn : RxResultFn < NoInfer < W > , XA , XE >
1368- readonly disableRefresh ?: boolean | undefined
1432+ readonly updateToValue : ( value : OW , current : NoInfer < A > ) => NoInfer < W >
1433+ readonly fn : RxResultFn < NoInfer < OW > , XA , XE >
13691434 }
13701435 ) : (
1371- self : Rx < A >
1372- ) => Writable < A , W >
1373- < A , XA , XE , W = A extends Result . Result < infer _A , infer _E > ? _A : A > (
1374- self : Rx < A > ,
1436+ self : Writable < A , Rx < Result . Result < W , unknown > > >
1437+ ) => RxResultFn < OW , XA , XE >
1438+ < A , W , XA , XE , OW = A extends Result . Result < infer _A , infer _E > ? _A : A > (
1439+ self : Writable < A , Rx < Result . Result < W , unknown > > > ,
13751440 options : {
1376- readonly updateToValue : (
1377- value : W ,
1378- current : NoInfer < A >
1379- ) => A extends Result . Result < infer _A , infer _E > ? _A : A
1380- readonly fn : RxResultFn < NoInfer < W > , XA , XE >
1381- readonly disableRefresh ?: boolean | undefined
1441+ readonly updateToValue : ( value : OW , current : NoInfer < A > ) => NoInfer < W >
1442+ readonly fn : RxResultFn < NoInfer < OW > , XA , XE >
13821443 }
1383- ) : Writable < A , W >
1384- } = dual ( 2 , < A , W , XA , XE > (
1385- self : Rx < A > ,
1444+ ) : RxResultFn < OW , XA , XE >
1445+ } = dual ( 2 , < A , W , OW , XA , XE > (
1446+ self : Writable < A , Rx < Result . Result < W , unknown > > > ,
13861447 options : {
1387- readonly updateToValue : ( value : W , current : A ) => A extends Result . Result < infer _A , infer _E > ? _A : A
1388- readonly fn : RxResultFn < W , XA , XE >
1389- readonly disableRefresh ?: boolean | undefined
1448+ readonly updateToValue : ( value : OW , current : A ) => W
1449+ readonly fn : RxResultFn < OW , XA , XE >
13901450 }
1391- ) : Writable < A , W > => {
1392- let counter = 0
1393- const argRx = state ( [ counter , undefined as A | undefined ] as const )
1394- return writable ( ( get ) => {
1395- let lastValue = get . once ( self )
1396- get . subscribe ( self , ( value ) => {
1397- lastValue = value
1398- if ( ! Result . isResult ( value ) ) {
1399- return get . setSelf ( value )
1400- }
1401- const current = Option . getOrUndefined ( get . self < Result . Result < any , any > > ( ) ) !
1402- if ( Result . isSuccess ( current ) && Result . isSuccess ( value ) ) {
1403- if ( value . timestamp >= current . timestamp ) {
1404- get . setSelf ( value )
1405- }
1406- } else {
1407- get . setSelf ( lastValue )
1408- }
1409- } )
1410- let lastSetSuccess : A | undefined
1411- get . subscribe ( argRx , ( [ , arg ] ) => {
1412- if ( arg === undefined ) {
1413- return
1414- }
1415- lastSetSuccess = arg
1416- get . setSelf ( arg )
1417- } )
1418- get . subscribe ( options . fn , ( value ) => {
1419- if ( value . waiting || Result . isInitial ( value ) ) {
1420- return
1421- } else if ( Result . isFailure ( value ) ) {
1422- return get . setSelf ( lastValue )
1423- }
1424- if ( options . disableRefresh !== true ) {
1425- return get . refresh ( self )
1426- }
1427- const current = Option . getOrUndefined ( get . self < Result . Success < any , any > > ( ) ) !
1428- if ( current === lastSetSuccess ) {
1429- get . setSelf ( Result . success ( current . value ) )
1430- }
1451+ ) : RxResultFn < OW , XA , XE > => {
1452+ const transition = state < Result . Result < W , unknown > > ( Result . initial ( ) )
1453+ return fn ( ( arg : OW , get ) => {
1454+ const value = options . updateToValue ( arg , get ( self ) )
1455+ get . set ( transition , Result . success ( value , { waiting : true } ) )
1456+ get . set ( self , transition )
1457+ get . set ( options . fn , arg )
1458+ return Effect . onExit ( get . result ( options . fn , { suspendOnWaiting : true } ) , ( exit ) => {
1459+ get . set ( transition , Result . fromExit ( Exit . as ( exit , value ) ) )
1460+ return Effect . void
14311461 } )
1432- return lastValue
1433- } , ( ctx , value ) => {
1434- const current = ctx . get ( self )
1435- const arg = options . updateToValue ( value , current )
1436- ctx . set ( argRx , [ ++ counter , Result . isResult ( current ) ? Result . success ( arg , { waiting : true } ) as A : arg as A ] )
1437- ctx . set ( options . fn , value )
1438- } , ( refresh ) => {
1439- refresh ( self )
14401462 } )
14411463} )
14421464
0 commit comments