Awaited Assign operation

Proposal: GitHub - wentout/awaited-assign: async set feature

Help me please to convert it to https://github.com/tc39/awaited-assignment

Let consider the following JavaScript code piece we may use on modern engines today:

'use strict';

const myObj = {};
let field = 123;

Object.defineProperty( myObj, 'field', {
	async get () {
		return new Promise( ( resolve, reject ) => {
			setTimeout( () => {
				resolve( field );
			}, 1000 );
		} );
	},
	async set ( value ) {
		new Promise( ( resolve, reject ) => {
			setTimeout( () => {
				field = value;
				resolve( field );
			}, 100 );
		} );
	}
} );

This code example above is fully functional and working at least via V8 runtime. Having Async Getters for today we allowed do consder that Setter is also asynchronous, but, unfortunately while being asynchronous indeed we are not allowed to track this operation. So having this code piece below is a scenario when we lack of instrumentation:

( async () => {
	console.log( 'initial : ', await myObj.field );
	console.log( 'the moment of assignment invocation : ', myObj.field = 321 );
	console.log( 'real value during changes happening : ', field );
	console.log( 'reading assigned value after change : ', await myObj.field );
	console.log( 'real value when changes indeed made : ', field );
} )();

Here we see the moment between assignment operator invocation and real value change today is unpredictable.

Thus let assume we may use the following construct to keep eye on this somehow:

await myObj.field = value;

This means Assignment Operation may have Asynchronous Behaviour for consistency with Async Getter

This is already valid JS, the assignment will return the RHS value. e.g:

let obj = {};
console.log(await obj.foo = Promise.resolve(42)); // logs 42

EDIT: I'm wrong. To be valid syntax today it needs to be await (obj.foo = v)

Thank you @aclaymore
Though anyway you aware of right-hand side of assignment operator, where I aware of left-hand side. As we already got async setters then how to track that setter promise. So I wish it returned on operation you are reviewing.

Assignment maps to the [[set]] method of meta-object-protocol, which internally does already have a return value: a boolean.

The true/false denotes if the assignment was successful or not. In strict-mode, the assignment returning false will lead to an exception. In sloppy mode it is a silent failure.

main();
function main() {
    "use strict";
    const obj = {};
    console.log(Reflect.set(obj, "foo", 1)); // true
    Object.freeze(obj);
    console.log(Reflect.set(obj, "bar", 1)); // false
    try {
        obj.bar = 1;
    } catch (err) {
        console.log(err.constructor.name) // TypeError
    }  
}

I'm curious, why not use a method?

const myObj = {
    assign(field, value) {
        return new Promise(resolve => {
            setTimeout( () => {
                myObj[field] = value;
		        resolve(value);
	        }, 100);
        });
    }
};

await myObj.assign("foo", 1);
1 Like

Uh, being able to use a promise-returning method in a property descriptor doesn't mean that JS has "asynchronous getters". In fact { async get field() {…} } syntax is not allowed. Why not just use a normal method?

See also Async Getters and Setters. Is it Possible? | by David Barral | Trabe | Medium or ecmascript 6 - (ES6) class (ES2017) async / await getter - Stack Overflow.