Obecnie czytam Async Javascript Trevora Burnhama. Jak dotąd to była świetna książka.
Mówi o tym, że ten fragment kodu i console.log są „asynchroniczne” w konsoli Safari i Chrome. Niestety nie mogę tego powtórzyć. Oto kod:
var obj = {};
console.log(obj);
obj.foo = 'bar';
// my outcome: Object{}; 'bar';
// The book outcome: {foo:bar};
Gdyby to było asynchroniczne, spodziewałbym się, że wynik będzie wynikiem książek. console.log () jest umieszczana w kolejce zdarzeń do momentu wykonania całego kodu, a następnie jest uruchamiana i miałby właściwość bar.
Wygląda na to, że działa synchronicznie.
Czy uruchamiam ten kod źle? Czy console.log faktycznie jest asynchroniczna?
javascript
asynchronous
Witaj świecie
źródło
źródło
console.log()
to nie zawsze pokazuje poprzednią wartość. Rozwiązaniem, jeśli tak się stanie, jest przekonwertowanie wszystkiego, co próbujesz, naconsole.log()
ciąg, który jest niezmienny, więc nie podlega temu problemowi. Tak więc z doświadczeniaconsole.log()
wynika, że istnieją pewne problemy z asynchronizacją, prawdopodobnie związane z organizowaniem danych przez granice procesów. Nie jest to zamierzone zachowanie, ale jest efektem ubocznym tego, jakconsole.log()
działa wewnętrznie (osobiście uważam to za błąd).Odpowiedzi:
console.log
nie jest znormalizowany, więc zachowanie jest raczej niezdefiniowane i można je łatwo zmienić od wydania do wydania narzędzi programistycznych. Twoja książka prawdopodobnie jest nieaktualna, podobnie jak moja odpowiedź wkrótce.W naszym kodzie nie ma znaczenia, czy
console.log
jest on asynchroniczny, czy nie, nie zapewnia żadnego rodzaju wywołania zwrotnego; a przekazane wartości są zawsze przywoływane i obliczane w momencie wywołania funkcji.Tak naprawdę nie wiemy, co się wtedy stanie (OK, moglibyśmy, ponieważ Firebug, Chrome Devtools i Opera Dragonfly są open source). Konsola będzie musiała gdzieś przechowywać zarejestrowane wartości i wyświetli je na ekranie. Renderowanie będzie na pewno przebiegać asynchronicznie (ograniczane do aktualizacji limitów szybkości), podobnie jak przyszłe interakcje z zarejestrowanymi obiektami w konsoli (np. Rozwijanie właściwości obiektu).
Konsola może więc albo sklonować (serializować) zmienne obiekty, które zarejestrowałeś, albo będzie przechowywać do nich odniesienia. Pierwsza nie działa dobrze z głębokimi / dużymi obiektami. Ponadto przynajmniej początkowe renderowanie w konsoli prawdopodobnie pokaże „bieżący” stan obiektu, tj. Ten, w którym został zalogowany - w Twoim przykładzie widać
Object {}
.Jednak po rozwinięciu obiektu w celu dokładniejszego zbadania jego właściwości jest prawdopodobne, że konsola będzie przechowywać tylko odniesienie do obiektu i jego właściwości, a wyświetlenie ich teraz pokaże ich bieżący (już zmutowany) stan. Jeśli klikniesz na
+
, powinieneś być w stanie zobaczyćbar
nieruchomość w swoim przykładzie.Oto zrzut ekranu, który został opublikowany w raporcie o błędzie, aby wyjaśnić ich „naprawę”:
Tak więc do niektórych wartości można się odwoływać długo po ich zarejestrowaniu, a ich ocena jest raczej leniwa („w razie potrzeby”). Najbardziej znanym przykładem tej rozbieżności jest pytanie Czy konsola JavaScript Chrome jest leniwa w obliczaniu tablic?
Sposób obejścia problemu polega na tym, aby zawsze rejestrować zserializowane migawki obiektów, np. Przez wykonanie
console.log(JSON.stringify(obj))
. To zadziała jednak tylko dla nieokrągłych i raczej małych obiektów. Zobacz także Jak mogę zmienić domyślne zachowanie console.log w przeglądarce Safari? .Lepszym rozwiązaniem jest użycie punktów przerwania do debugowania, w których wykonywanie całkowicie zatrzymuje się i można sprawdzić bieżące wartości w każdym punkcie. Używaj rejestrowania tylko z danymi seryjnymi i niezmiennymi.
źródło
console.log
nadal jest asynchroniczny w Chrome, ponieważ miał 8 lat (patrz stackoverflow.com/questions/7389069/ ... ), jedyną rzeczą, która się zmienia, jest to, że teraz Chrome wyświetla migawkę obiektu referencyjnego w podczas wywołaniaconsole.log
(jeśli rozwiniesz zarejestrowany obiekt, zobaczysz jego końcowe właściwości i wartości po operacjach mutacji, które wykonałeś poconsole.log
), czyconsole.log
rzeczywiście jest synchroniczny?JSON.parse(JSON.stringify(obj))
jak wspomniano w komentarzu tutaj , otrzymasz migawkę w postaci obiektu, zamiast ciągu.To nie jest tak naprawdę odpowiedź na pytanie, ale może się przydać komuś, kto natknął się na ten post, a komentarz był zbyt długi:
window.console.logSync = (...args) => { try { args = args.map((arg) => JSON.parse(JSON.stringify(arg))); console.log(...args); } catch (error) { console.log('Error trying to console.logSync()', ...args); } };
Tworzy to pseudosynchroniczną wersję programu
console.log
, ale z tymi samymi zastrzeżeniami, które zostały wymienione w zaakceptowanej odpowiedzi.Ponieważ wydaje się, że w tej chwili większość przeglądarek
console.log
jest w pewien sposób asynchroniczna, możesz chcieć użyć takiej funkcji w pewnych sytuacjach.źródło
Podczas korzystania z console.log:
a = {}; a.a=1;console.log(a);a.b=function(){}; // without b a = {}; a.a=1;a.a1=1;a.a2=1;a.a3=1;a.a4=1;a.a5=1;a.a6=1;a.a7=1;a.a8=1;console.log(a);a.b=function(){}; // with b, maybe a = {}; a.a=function(){};console.log(a);a.b=function(){}; // with b
w pierwszej sytuacji obiekt jest na tyle prosty, że konsola może go „zdefiniować”, a następnie przedstawić; ale w innych sytuacjach a jest zbyt „skomplikowane”, aby „zdefiniować”, więc konsola pokaże zamiast tego obiekt w pamięci, i tak, kiedy na to spojrzysz, b jest już dołączone do a.
źródło