在这个问题中:How to add a custom property or method to a promise?有关于如何添加属性的简单解决方案"预先知道属性时
对于clientside-require
模块,我试图启用require()
函数加载的包,将自己的属性附加到require()
返回的承诺。例如,要启用此功能:
var promise_view_loader = require("clientside-view-loader")
promise_view_loader_package
.load("clientside-view-modal-login_signup")
.generate()
.then((modal)=>{
document.body.appendChild(modal);
modal.show("login");
})
或者
var promies_request_package = require("clientside-request")
promies_request_package
.request("https://google.com")
.then((response)=>{
console.log(response)
})
问题是我们要求的每个软件包都应该能够定义自己的自定义属性。换句话说, 我们不知道同步属性 。首先,我们需要解析promise_module_properties
,然后根据这些属性,必须修改require
生成的承诺的属性。
这可能吗?
答案 0 :(得分:-1)
正如Bergi所说,仅仅因为我们可以这样做并不意味着我们应该。事实上,我强烈建议反对它。
无论如何,可以使用builder和代理:
假设属性的异步定义如下:
var properties_to_append = {
load : function(path){
return this.then((view_loader)=>{ console.log("loading " + path); return view_loader.load(path)}) // define `view_loader.load()` to the view_loader promise
},
generate : function(options){
return this.then((compiler)=>{ return compiler.generate(options) })
},
}
var promise_properties = Promise.resolve(properties_to_append);
然后利用下面定义的AsyncPropertyPromise
类,按预期工作:
var async_property_promise = new AsyncPropertyPromise(require("clientside-view-loader"), promise_properties);
async_property_promise // works
.load("clientside-view-modal-login_signup") // works
.generate() // works
.then((modal)=>{
document.body.appendChild(modal);
modal.show("login");
})
AsyncPropertyPromise:
var unknown_properties_deferment_handler = {
return_defined_target_value : function(target, prop){
var value = target[prop];
var bound_value = typeof value == 'function' ? value.bind(target) : value; // bind functions to target, as they would expect
return bound_value; // return the requested name or parameters
},
get: function(target, prop) {
if(prop in target){
return this.return_defined_target_value(target, prop); // if the requested method or parameter is in the target object, just return it
} else {
return target.promise_to_attempt_to_get_async_property(prop);
}
}
};
class AsyncPropertyPromise {
constructor(original_promise, promise_properties) {
this.original_promise = original_promise;
this.promise_properties = promise_properties;
var proxied_self = new Proxy(this, unknown_properties_deferment_handler);
return proxied_self;
}
then(...args) {
return this.original_promise.then(...args);
}
catch(...args){
return this.original_promise.catch(...args);
}
promise_to_attempt_to_get_async_property(property){
/*
1. return a function - NOTE - this assumes that any property not statically defiend is a function
2. make that function resolve with an AsnycPropertyPromise that
a. returns the value of the property (method) if it exists
b. throws error if it does not
*/
return function(...args){ // 1
var raw_response_promise = this.promise_properties // 2
.then((loaded_properties)=>{
if(!(property in loaded_properties)) throw "property not defined"; // 2.a
var value = loaded_properties[property];
var bound_value = value.bind(this); // bind to original_promise
return bound_value(...args); // evaluate and return response while passing orig arguments; see `spread` https://stackoverflow.com/a/31035825/3068233
});
var async_proxied_response_promise = this._wrap_a_promise(raw_response_promise);
return async_proxied_response_promise;
}
}
_wrap_a_promise(raw_promise){
return new this.constructor(raw_promise, this.promise_properties);
}
}