Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

204
Visualizações
¿Cómo se harían los getters y setters de JavaScript asíncronos?

Piense en cómo Rails, por ejemplo, le permite definir una propiedad asociada con otra:

 class Customer < ActiveRecord::Base has_many :orders end

Esto no configura una columna de base de datos para orders . En su lugar, crea un captador de orders , lo que nos permite hacer

 @orders = @customer.orders

Que va y obtiene los objetos de orders relacionados.

En JS, podemos hacer eso fácilmente con captadores:

 { name: "John", get orders() { // get the order stuff here } }

Pero Rails es sync , y en JS, si en nuestro ejemplo, como es razonable, vamos a la base de datos, lo estaríamos haciendo asíncrono .

¿Cómo crearíamos getters asíncronos (y setters, para el caso)?

¿Le devolveríamos una promesa que finalmente se resuelve?

 { name: "John", get orders() { // create a promise // pseudo-code for db and promise... db.find("orders",{customer:"John"},function(err,data) { promise.resolve(data); }); return promise; } }

que nos permitiría hacer

 customer.orders.then(....);

¿O lo haríamos con un estilo más angular, donde lo resolveríamos automáticamente en un valor?

En resumen, ¿cómo implementamos captadores asíncronos?

over 4 years ago · Santiago Trujillo
3 Respostas
Responde à pergunta

0

Las palabras clave de la función get y set parecen ser incompatibles con la palabra clave async . Sin embargo, dado que async / await es solo un envoltorio alrededor de Promise s, puede usar Promise para hacer que sus funciones sean " await -able".

Nota: Debería ser posible usar el método Object.defineProperty para asignar una función async a un definidor o captador.


adquiridor

Las promesas funcionan bien con captadores.

Aquí, estoy usando la función incorporada util.promisify() de Node.js 8 que convierte una devolución de llamada de estilo de nodo ("devolución de nodo") en una Promise en una sola línea. Esto hace que sea muy fácil escribir un captador capaz de await .

 var util = require('util'); class Foo { get orders() { return util.promisify(db.find)("orders", {customer: this.name}); } }; // We can't use await outside of an async function (async function() { var bar = new Foo(); bar.name = 'John'; // Since getters cannot take arguments console.log(await bar.orders); })();

setter

Para los setters, se vuelve un poco raro.

Por supuesto, puede pasar una Promesa a un setter como argumento y hacer lo que sea por dentro, ya sea que espere a que se cumpla la Promesa o no.

Sin embargo, me imagino que un caso de uso más útil (¡el que me trajo aquí!) sería usar el setter y luego await que la operación se complete en cualquier contexto desde el que se haya utilizado el setter. Desafortunadamente, esto no es posible ya que el valor de retorno de la función setter se descarta .

 function makePromise(delay, val) { return new Promise(resolve => { setTimeout(() => resolve(val), delay); }); } class SetTest { set foo(p) { return p.then(function(val) { // Do something with val that takes time return makePromise(2000, val); }).then(console.log); } }; var bar = new SetTest(); var promisedValue = makePromise(1000, 'Foo'); (async function() { await (bar.foo = promisedValue); console.log('Done!'); })();

En este ejemplo, Done! se imprime en la consola después 1 segundo y el Foo se imprime 2 segundos después de eso. Esto se debe a que await está esperando que se cumpla el valor promisedValue y nunca ve la Promise utilizada/generada dentro del setter.

over 4 years ago · Santiago Trujillo Relatório

0

En cuanto a captadores asíncronos, puede hacer algo como esto:

 const object = {}; Object.defineProperty(object, 'myProperty', { async get() { // Your awaited calls return /* Your value */; } });

Más bien, el problema surge cuando se trata de setters asincrónicos. Dado que la expresión a = b siempre produce b , no hay nada que se pueda hacer para evitar esto, es decir, ningún setter en el objeto que tenga la propiedad a puede anular este comportamiento.
Como también me topé con este problema, pude darme cuenta de que los setters asincrónicos eran literalmente imposibles. Entonces, me di cuenta de que tenía que elegir un diseño alternativo para usar en lugar de los setters asíncronos. Y luego se me ocurrió la siguiente sintaxis alternativa:

 console.log(await myObject.myProperty); // Get the value of the property asynchronously await myObject.myProperty(newValue); // Set the value of the property asynchronously

Lo tengo funcionando con el siguiente código,

 function asyncProperty(descriptor) { const newDescriptor = Object.assign({}, descriptor); delete newDescriptor.set; let promise; function addListener(key) { return callback => (promise || (promise = descriptor.get()))[key](callback); } newDescriptor.get = () => new Proxy(descriptor.set, { has(target, key) { return Reflect.has(target, key) || key === 'then' || key === 'catch'; }, get(target, key) { if (key === 'then' || key === 'catch') return addListener(key); return Reflect.get(target, key); } }); return newDescriptor; }

que devuelve un descriptor para una propiedad asíncrona, dado otro descriptor que puede definir algo que parece un setter asíncrono.

Puede utilizar el código anterior de la siguiente manera:

 function time(millis) { return new Promise(resolve => setTimeout(resolve, millis)); } const object = Object.create({}, { myProperty: asyncProperty({ async get() { await time(1000); return 'My value'; }, async set(value) { await time(5000); console.log('new value is', value); } }) });

Una vez que haya configurado una propiedad asíncrona como la anterior, puede configurarla como ya se ilustra:

 (async function() { console.log('getting...'); console.log('value from getter is', await object.myProperty); console.log('setting...'); await object.myProperty('My new value'); console.log('done'); })();
over 4 years ago · Santiago Trujillo Relatório

0

Lo siguiente permite setters asíncronos en controladores de proxy siguiendo la convención en la respuesta de Davide Cannizzo.

 var obj = new Proxy({}, asyncHandler({ async get (target, key, receiver) { await new Promise(a => setTimeout(a, 1000)) return target[key] }, async set (target, key, val, receiver) { await new Promise(a => setTimeout(a, 1000)) return target[key] = val } })) await obj.foo('bar') // set obj.foo = 'bar' asynchronously console.log(await obj.foo) // 'bar' function asyncHandler (h={}) { const getter = h.get const setter = h.set let handler = Object.assign({}, h) handler.set = () => false handler.get = (...args) => { let promise return new Proxy(()=>{}, { apply: (target, self, argv) => { return setter(args[0], args[1], argv[0], args[2]) }, get: (target, key, receiver) => { if (key == 'then' || key == 'catch') { return callback => { if (!promise) promise = getter(...args) return promise[key](callback) } } } }) } return handler }
over 4 years ago · Santiago Trujillo Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda