Рефакторинг функции и лучшее обещание цепочки - PullRequest
1 голос
/ 09 апреля 2019

У меня сейчас есть эта функция, и она работает:

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);

.. но мне было интересно, как я могу улучшить его, чтобы мне не приходилось связывать обещания каждый раз, когда мне нужно проверять вложенный объект?

Ответы [ 3 ]

2 голосов
/ 09 апреля 2019
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);
  });
1 голос
/ 09 апреля 2019

Преимущества метода, показанного ниже, состоят в том, что его использование представляет собой одну строку кода, и, что может быть более важно, «путь» может быть создан динамически

Краткое объяснение

путь (после «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);
0 голосов
/ 09 апреля 2019

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);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...