异步JavaScript的getter和setter怎么办? [英] How would one do async JavaScript getters and setters?

查看:97
本文介绍了异步JavaScript的getter和setter怎么办?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

想想Rails的方式,例如允许您将一个属性定义为与另一个属性相关联:

  Class客户<ActiveRecord :: Basehas_many:订单结尾 

这不会为 orders 设置数据库列.相反,它为 orders 创建了一个吸气剂,使我们可以进行

  @orders = @ customer.orders 

去获取相关的 orders 对象.

在JS中,我们可以使用吸气剂轻松做到这一点:

  {名称:约翰",获取订单(){//在此处获取订单商品}} 

但是Rails是 sync ,并且在JS中,如果在我们的示例中,如果合理的话,我们要去数据库,我们将在 async 中进行操作./p>

我们将如何创建异步获取器(和设置器)?

我们会返回最终解决的诺言吗?

  {名称:约翰",获取订单(){//创建一个承诺//db和promise的伪代码...db.find("orders",{customer:"John"}},function(err,data){promise.resolve(data);});回报承诺;}} 

这将使我们能够做到

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

还是我们会采用更具角度的样式,将其自动解析为值?

总而言之,我们如何实现异步获取器?

解决方案

get set 函数关键字似乎与 async 关键字.但是,由于 async / await 只是 Promise 的包装,因此您可以使用 Promise 进行您的函数"等待-可以".

注意:应该可以使用 Object.defineProperty 方法将 async 函数分配给setter或getter.


getter

承诺与吸气剂配合得很好.

在这里,我正在使用Node.js 8内置的 util.promisify()函数,该函数将节点样式回调("nodeback")转换为 Promise 一行.这使得编写一个 await -getter变得非常容易.

  var util = require('util');Foo类{获取订单(){return util.promisify(db.find)("orders",{customer:this.name});}};//我们不能在异步函数之外使用await(异步功能(){var bar = new Foo();bar.name ='约翰';//由于getter不能接受参数console.log(等待bar.orders);})(); 


设置器

对于二传手来说,这有点奇怪.

您当然可以将Promise传递给setter作为参数,并在内部做任何事情,无论您是否等待Promise的实现.

但是,我想一个更有用的用例(将我带到这里!)将用于setter,然后 await 使该操作在setter的任何上下文中完成从使用.不幸的是,这是不可能的,因为 setter函数的返回值已被丢弃.

  function makePromise(delay,val){返回新的Promise(resolve => {setTimeout(()=> resolve(val),delay);});}类SetTest {设置foo(p){返回p.then(function(val){//用val做一些需要花费时间的事情返回makePromise(2000,val);}).then(console.log);}};var bar = new SetTest();var promisedValue = makePromise(1000,'Foo');(异步功能(){等待(bar.foo = promisedValue);console.log('完成!');})(); 

在此示例中,在 1 秒后将 Done!打印到控制台,并在 2 中打印 Foo 代码>秒之后.这是因为 await 正在等待 promisedValue 履行,并且它从未看到setter内部使用/生成的 Promise .

Think of how Rails, e.g. allows you to define a property as associated with another:

class Customer < ActiveRecord::Base
  has_many :orders
end

This does not set up a database column for orders. Instead, it creates a getter for orders, which allows us to do

@orders = @customer.orders

Which goes and gets the related orders objects.

In JS, we can easily do that with getters:

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

But Rails is sync, and in JS, if in our example, as is reasonable, we are going to the database, we would be doing it async.

How would we create async getters (and setters, for that matter)?

Would we return a promise that eventually gets resolved?

{
   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;
   }
}

which would allow us to do

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

Or would we do it more angular-style, where we would automatically resolve it into a value?

To sum, how do we implement async getters?

解决方案

The get and set function keywords seem to be incompatible with the async keyword. However, since async/await is just a wrapper around Promises, you can just use a Promise to make your functions "await-able".

Note: It should be possible to use the Object.defineProperty method to assign an async function to a setter or getter.


getter

Promises work well with getters.

Here, I'm using the Node.js 8 builtin util.promisify() function that converts a node style callback ("nodeback") to a Promise in a single line. This makes it very easy to write an await-able getter.

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

For setters, it gets a little weird.

You can of course pass a Promise to a setter as an argument and do whatever inside, whether you wait for the Promise to be fulfilled or not.

However, I imagine a more useful use-case (the one that brought me here!) would be to use to the setter and then awaiting that operation to be completed in whatever context the setter was used from. This unfortunately is not possible as the return value from the setter function is discarded.

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!');
})();

In this example, the Done! is printed to the console after 1 second and the Foo is printed 2 seconds after that. This is because the await is waiting for promisedValue to be fulfilled and it never sees the Promise used/generated inside the setter.

这篇关于异步JavaScript的getter和setter怎么办?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆