Allegro Seller Info 0.1.5

tech • 773 słowa • 4 minuty czytania

Na przestrzeni ostatnich dwóch dni zauważyłem kilka małych problemów w działaniu mojego allegrowego UserJS-a. Czyżby jakieś nowe zmiany na stronach portalu popsuły mój skrypcik?

Jednym z problemów jest wyświetlanie niektórych nazw sprzedających na liście ofert jako “undefined”. Okazuje się, że z jakiegoś powodu niektóre instancje struktury item.seller wyekstrahowane z reactowych “propsów” zawierają okrojone dane. Brakuje kluczowych dla skryptu pól z nazwą użytkownika (login) i adresem do jego listy wystawionych ofert (userListingUrl).

Druga sprawa dotyczy strony z opisem aukcji i chyba też występuje losowo. A objawia się typowym niedziałaniem skryptu, bo nie pokazuje się informacja o miejscu lokacji wystawiającego. Widzę, że znikła z globalnej przestrzeni nazw zmienna __PROPS__ALLEGRO_SHOWOFFER_SUMMARY__ na bazie której skrypt “wie”, że znajduje się na stronie oferty.

Czyżby nadchodziły jakieś zmiany na stronach portalu? A może to chwilowe problemy techniczne? Wcześniej już widziałem podobne “akcje”, ale wszystko po krótkim czasie wracało do normy. Może tym razem będzie podobnie, więc dla pewności postanowiłem odczekać 24 godziny nim zacznę coś robić. Powinno wystarczyć na rozwiązanie problemów technicznych lub ustabilizowanie potencjalnych zmian.

Ostatecznie okazało się, że to jednak musiały być jakieś techniczne aspekty, bo wszystko zaczęło działać poprawnie. I miałoby nie być nowej wersji skryptu, ale przy okazji przyjrzałem się innemu problemowi, który kiedyś “załatałem” prostym obejściem, a coś nie do końca chyba się to udało.


Przy budowie części skryptu działającego na stronach aukcji miałem dziwny problem ze znikaniem wstawionego elementu do DOM-a strony, szczególnie w sytuacji gdy strona zostawała otwarta w tle. Wtedy powiązałem to z pewnym “ficzerem” w Chromie1 i zastosowałem prosty hack. Wszystko wskazywało, że jest to jakiś błąd w tej przeglądarkowej funkcjonalności, błąd w skryptach na stronie lub wzajemne oddziaływanie na siebie tych dwóch rzeczy. Miałem w planach nawet bliższe przyjrzenie się temu, aby zreprodukować problem na prostszej stronie i stworzyć jakiś PoC, jeśli faktycznie byłby to błąd w przeglądarce. Ale z braku czasu to olałem. Wszakże workaround działał dobrze…

Z czasem jednak zaczęło coś z tym szwankować, bo zauważałem dziwne artefakty. Dodany element albo znikał tuż po pojawieniu się, albo pojawiał się i znikał w dziwnych sytuacjach (np. po odświeżeniu strony). Zacząłem się wtedy zastanawiać, czy aby na pewno powiązanie tego z “chromowym throttlingiem” było słuszne.

Miałem pewne podejrzenia, że może to jednak jest “celowe” i poprawne “działanie strony”. Może jakiś kod modyfikuje lub przebudowuje fragment struktury dokumentu, gdzie lądują dodawane przez skrypt elementy. Poświadczyły to proste testy polegające na dodaniu tej samej wstawki w innym miejscu strony. I zgodnie z przypuszczeniami wstawiony element nie wykazywał podobnego zachowania do tego w nagłówku aukcji, wręcz zachowywał się poprawnie (“wyświetlał”) w każdej sytuacji. Czyli sprawa jest już jasna…

Nie chciałem zbytnio marnować czasu na debugowanie i poszukiwanie oryginalnego kodu strony za to odpowiadającego, aby sprawdzić co tam się dzieje i jakoś wykorzystać to do znalezienia rozwiązania. Poszedłem inną prostszą drogą i z wykorzystaniem MutationObserver łapię zdarzenia usunięcia elementów z nagłówka aukcji i w razie potrzeby dodaję ponownie swoje bebechy:

var mutationObserver = new MutationObserver(function (mutations) {
	mutations.forEach(function (m) {
		if (m.removedNodes.length != 0 && itemNode.getElementsByClassName(cssName).length == 0)
			UpdateOffer(); 
	});
});
mutationObserver.observe(itemNode, { childList: true, subtree: true });

Kod ten rozwiązał cały problem związany z dziwnym zachowaniem skryptu na stronach aukcji. Już nic nie znika, dodane informacje zawsze wyświetlają się poprawnie, niezależnie czy strona została otwarta w tle, czy ją kilkukrotnie odświeżono. Jest tak jak powinno być. Wreszcie!

A przy okazji patrząc na te callbacki dla obserwatora zmian, zauważyłem że są one nieco przekombinowane i w pewnych momentach docelowa funkcja UpdateXXX może zostać wykonana wiele razy w ramach jednej “paczki” zdarzeń. Fajnie byłoby to jakoś uprościć i zagwarantować, że na jedne wywołanie callbacka, niezależnie od ilości zdarzeń, docelowy update call zostanie wykonany tylko jeden raz.

Zaskakująco łatwo to osiągnąć sprawdzając czy tablica zdarzeń zawiera chociaż jedno wystąpienie poszukiwanego zdarzenia i dopiero wtedy przejść do dalszej akcji. Zdecydowanie jest to czytelniejsze i prostsze niż paskudne iterowanie po listach i kombinowanie…

Dla dzisiejszego, opisanego wyżej obserwatora, poprawiony kod może wyglądać tak:

var mutationObserver = new MutationObserver(function (mutations) {
	const delEvt = mutations.findIndex(m => m.removedNodes.length != 0) != -1;
	if (delEvt && itemNode.getElementsByClassName(cssName).length == 0)
		UpdateOffer(); 
});

Adekwatnie dla strony z listą ofert ciało functora może przyjąć postać:

var mutationObserver = new MutationObserver(function (mutations) {
	const updEvt = mutations.findIndex(m => m.attributeName == 'class' && m.target.className.indexOf(' ') == -1) != -1;
	if (updEvt)
		UpdateList(); 
});

No i te raz to wygląda i działa bardziej po ludzku ;)

I tymi sposobem udało się poprawić kilka paskudnych rzeczy i jednak wydać kolejna wersje skryptu, który można znaleźć w repo UserScripts. Standardowo, dzięki auto-aktualizacji skrypt powinien sam się zaktualizować.


Przypisy

  1. Mowa tutaj o “Background Tab Resource Load Throttling”, o szczegółach można poczytać w notce opisującej pierwszą implementację skryptu dla strony aukcji. ↩︎

Komentarze (0)

Dodaj komentarz

/dozwolony markdown/

/nie zostanie opublikowany/