dei*_*tch 17 javascript promise
想想Rails如何允许您将属性定义为与另一个属性相关联:
class Customer < ActiveRecord::Base
has_many :orders
end
Run Code Online (Sandbox Code Playgroud)
这不会为其设置数据库列orders.相反,它创造了一个吸气剂orders,这使我们能够做到
@orders = @customer.orders
Run Code Online (Sandbox Code Playgroud)
哪个去获取相关orders对象.
在JS中,我们可以使用getter轻松实现:
{
name: "John",
get orders() {
// get the order stuff here
}
}
Run Code Online (Sandbox Code Playgroud)
但是Rails是同步的,而在JS中,如果在我们的例子中,合理的话,我们将进入数据库,我们将把它做为异步.
我们如何创建异步getter(以及setter)?
我们会回复最终得到解决的承诺吗?
{
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;
}
}
Run Code Online (Sandbox Code Playgroud)
这将允许我们这样做
customer.orders.then(....);
Run Code Online (Sandbox Code Playgroud)
或者我们会做更多角度风格,我们会自动将其解析为值吗?
总之,我们如何实现异步吸气剂?
该get和set功能的关键字似乎有不兼容的async关键字.但是,因为async/ await只是Promises 的包装,你可以使用a Promise来使你的函数" await-able".
注意:应该可以使用该Object.defineProperty方法将async函数分配给setter或getter.
承诺与吸气剂配合良好.
在这里,我使用Node.js 8内置util.promisify()函数将节点样式回调("nodeback")转换Promise为单行.这使得编写一个await可用的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);
})();
Run Code Online (Sandbox Code Playgroud)
对于制定者来说,它有点奇怪.
您当然可以将Promise作为参数传递给setter,并在内部做任何事情,无论您是否等待Promise得到满足.
但是,我想一个更有用的用例(将我带到这里的那个!)将用于setter,然后await在任何使用setter的上下文中完成该操作.遗憾的是,这是不可能的,因为丢弃了来自setter函数的返回值.
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!');
})();
Run Code Online (Sandbox Code Playgroud)
在此示例中,Done!在1第二个之后将其打印到控制台,然后在几秒钟之后Foo打印2.这是因为await等待promisedValue实现并且它永远不会看到Promisesetter内部使用/生成.
小智 -5
这是实现获取订单功能的方法
function get(name) {
return new Promise(function(resolve, reject) {
db.find("orders", {customer: name}, function(err, data) {
if (err) reject(err);
else resolve(data);
});
});
}
Run Code Online (Sandbox Code Playgroud)
你可以像这样调用这个函数
customer.get("John").then(data => {
// Process data here...
}).catch(err => {
// Process error here...
});
Run Code Online (Sandbox Code Playgroud)