2

Let's say we have an object:

const obj = { element }

and a Proxy with "asyncronous trap":

const proxy = new Proxy( obj, {
     get: async function(obj, prop) {
          if(prop === 'element') {
              // wait until child element appears ( - just for example,
              // in general this function returns delayed value)  
              const result = wait(obj[prop].querySelector('.child')); //promise
              return await result;
          }
    }
})

I've tried code above but it doesn't work. It seems like Proxy doesn't recognize async get as a trap and don't intercept getter.

How to fix that? Or:

Is there another way to get 'delayed' value of object's property without mutation of original object?

Asker
  • 71
  • 2
  • Can you be more detailed about expected behavior (i.e. how you want to use the proxy object), and a [minimal, reproducible example](https://stackoverflow.com/help/minimal-reproducible-example)? This code correctly gets a promise `new Proxy({}, {get: async (obj, prop) => console.log('intercepted')}).element`. – Dafang Cao Jul 09 '19 at 02:39
  • Remember that an `async function` is just a function that returns a promise. This should work just fine (apart from that your trap is broken when accessing anything else but `.element`), you just have to take care of waiting for the promise. No, there is no wait to make the asynchronous value appear immediately. – Bergi Aug 20 '19 at 05:17

1 Answers1

0

Try this: i've created two proxy, the first call a remote api, wait for response and set the target with value returned in the second proxy. The second proxy also get the values.

 let person = {
    name: "",
    gender: "",
    probability: "",
    count: ""
};

let callApi = {
    get: function( target, property, value ) {
        console.log( 'load from remote server...' );
        return async function( value ){
            return new Promise( async ( resolve, reject ) => {
                if ( typeof value === 'string' ) {
                    const response = await fetch( 'https://api.genderize.io/?name=' + value );
                    const data = await response.json();
                    resolve( data );
                } else {
                    reject( new TypeError( 'The value of "name" must be a string.' ) );
                };
            })
        }
    },
    set: function ( obj, property, value ) {
        return new Promise( ( resolve, reject ) => {
            console.log( 'save someting remotely...' );
            setTimeout( () => resolve( true ), 1000 )
        })
    }
};

let getData = {
    get: async ( target, property ) => {

        if( property === 'userDetails' ){
            return `${target.name} is a ${target.gender}`;
        } else if ( property === 'userInfo' ){
            if ( target.gender === "male" ){
                return "the user is a man";
            } else {
                return "the user is a woman";
            };
        } else {
            return target[property];
        };

        if ( target.property instanceof Promise ) {
            return target.property.then( resolve => target[property] = resolve );
        } else {
            return target[property];
        }
    },
    set: function ( target, property, data ) {
        //target[property] = value
        console.log( "property:" + property );

        if( data.name !== 'undefined' ){
            target['name'] = data.name;
            target['gender'] = data.gender
            target['probability'] = data.probability
            target['count'] = data.count;
        } else {
            target['name'] = '';
            target['gender'] = '';
            target['probability'] = '';
            target['count'] = '';
        };
        //console.log( target[property] );
    }
};

async function main() { 
    let api = new Proxy( person, callApi )
    let data = new Proxy( person, getData )
    data.save = await api.query( 'giuseppe' );   // await it here
    console.log( await data.userDetails );
};
// all begin here!!!
main();
Giuseppe Canale
  • 470
  • 7
  • 15