Преимущества метода, показанного ниже, состоят в том, что его использование представляет собой одну строку кода, и, что может быть более важно, «путь» может быть создан динамически
Краткое объяснение
путь (после «root» - window
в вашем случае) - это строка в точечной нотации, поэтому сначала разбейте эту строку на части
. Получив массив, используйте метод array.reduce, чтобы создать цепочкуиз обещаний - «семя» для array.reduce равно Promise.resolve(root)
, и каждое последующее обещание преобразуется (как в вашем коде) в «созданный» объект
Конечно, «поддерживающий» код больше, но конецРезультат так же просто, как
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);