[英]Refactoring function and better promise chaining
我目前有這個功能,它的工作原理:
function waitForObjectProperty(object, property) { return new Promise(function(resolve, reject) { Object.defineProperty(Object.prototype, property, { configurable: true, set: function(value) { Object.defineProperty(object, property, { value: value, }); resolve(object[property]); }, }); }); } waitForObjectProperty(window, "google").then(function(object) { waitForObjectProperty(object, "maps").then(function(object) { waitForObjectProperty(object, "places").then(function(object) { console.log('places object:', google.maps.places); }); }); }); setTimeout(function(){ window.google = {} }, 1000); setTimeout(function(){ window.google.maps = {} }, 2000); setTimeout(function(){ window.google.maps.places = {} }, 3000);
..但我想知道我怎么能改進它所以每次我必須檢查嵌套對象時我不必鏈接承諾?
const tapProp = property => object => waitForObjectProperty(object, property);
Promise.resolve(window)
.then(tapProp("google"))
.then(tapProp("maps"))
.then(tapProp("places"))
.then(function(object) {
console.log('places object:', google.maps.places);
});
下面顯示的方法的好處是它的使用是一行代碼,更重要的是,可以動態創建“路徑”
簡要說明
路徑(在“root” - window
之后)是點符號的字符串,因此首先將該字符串拆分為多個部分
使用生成的數組,使用array.reduce方法創建promises鏈 - Promise.resolve(root)
的“種子”是Promise.resolve(root)
,每個后續的promise都會解析(如在代碼中)到“created”對象
當然“支持”代碼更大,但最終結果就像
waitForNestedObject(window, 'some.very.long.path.that.you.can.even.build.dynamically.if.you.want');
function waitForNestedObject(root, objectPath) { var waitForObjectProperty = function (object, property) { return new Promise(function(resolve, reject) { Object.defineProperty(Object.prototype, property, { configurable: true, set: function(value) { Object.defineProperty(object, property, { value: value, }); resolve(object[property]); }, }); }); } var steps = objectPath.split('.'); return steps.reduce(function(p, step) { return p.then(function(object) { return waitForObjectProperty(object, step); }); }, Promise.resolve(root)); } // // use is simple now // waitForNestedObject(window, 'google.maps.places') .then(function(object) { console.log(object); }); setTimeout(function(){ window.google = {} }, 1000); setTimeout(function(){ window.google.maps = {} }, 2000); setTimeout(function(){ window.google.maps.places = {hello:'world'} }, 3000);
在現代的javascript中你可以寫如下 - (不知道為什么你不能使用現代的javascript(根據關於箭頭功能的另一個答案中的評論))
const waitForNestedObject = (root, objectPath) => { const waitForObjectProperty = (object, property) => new Promise((resolve, reject) => Object.defineProperty(Object.prototype, property, { configurable: true, set: function(value) { Object.defineProperty(object, property, { value: value, }); resolve(object[property]); }, })); return objectPath.split('.').reduce((p, step) => p.then(object => waitForObjectProperty(object, step)), Promise.resolve(root)); }; // // usage remains the same waitForNestedObject(window, 'google.maps.places') .then(object => console.log(object)); setTimeout(function(){ window.google = {} }, 1000); setTimeout(function(){ window.google.maps = {} }, 2000); setTimeout(function(){ window.google.maps.places = {hello:'world'} }, 3000);
function waitForObjectProperty(object, property) { return new Promise(function(resolve, reject) { Object.defineProperty(Object.prototype, property, { configurable: true, set: function(value) { Object.defineProperty(object, property, { value: value, }); resolve(object[property]); }, }); }); } // you can just return promise and then chainning waitForObjectProperty(window, "google") .then(object => waitForObjectProperty(object, "maps")) .then(object => waitForObjectProperty(object, "places")) .then(object => console.log('places object:', google.maps.places)); setTimeout(function(){ window.google = {} }, 1000); setTimeout(function(){ window.google.maps = {} }, 2000); setTimeout(function(){ window.google.maps.places = {} }, 3000);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.