SlideShare a Scribd company logo
ASYNCHRONOUS
JAVASCRIPT

GET STUFF DONE BY KNOWING WHEN STUFF IS DONE.
WANT TO HEAR A JAVASCRIPT JOKE?

CALLBACK LATER AND
I'LL TELL IT TO YA!
CALLBACKS ARE HOW JAVASCRIPT MANAGES THINGS THAT
NEED TO HAPPEN IN THE FUTURE
fnto dlvrucln( {
ucin eiePnhie)
cnoelg"eas te tk tig ltrly";
osl.o(Bcue hy ae hns ieal.)
}
fnto stpoe){
ucin eUJk(
cnoelg"h dntketmnaslk pn?)
osl.o(Wy o' lpoaic ie us";
stieu(eiePnhie 20)
eTmotdlvrucln, 00;
}
stpoe)
eUJk(;
EVENT PUMP
setUpJoke
deliverPunchline (after 2000 ms)

EXECUTION THREAD
setUpJoke
deliverPunchline
WHAT HAPPENS IF THE EXECUTION THREAD IS BUSY?
fnto dlvrucln( {
ucin eiePnhie)
cnoelg"eas svnhssm bds ttos";
osl.o(Bcue ee a oe aas ato.)
}
fnto cnrvdxml( {
ucin otieEape)
cnoelg"h i sxari o svn";
osl.o(Wy s i fad f ee?)
stieu(eiePnhie 20)
eTmotdlvrucln, 00;
fnPieatrFrETEEYLRENME)
idrmFcoso(XRML_AG_UBR;
}
fnto cnrvdxml(;
ucin otieEape)
EVENT PUMP
contrivedExample
deliverPunchline in 2000 ms (2000 ms are up!)

EXECUTION THREAD
contrivedExample (still finding factors)
deliverPunchline WAY after 2000 ms!
IN JAVASCRIPT, EVENTS
ARE BLOCKED BY
CURRENTLY EXECUTING
CODE.
"In JavaScript, events are blocked by currently
executing code." -RonTime
"
"In JavaScript, events are blocked
by currently executing code." RonTime
" -Your Name Here
EVENT PUMP
user furiously smashing keyboard event
scroll event
mouse click event
deliverPunchline in 100 ms

EXECUTION QUEUE
contrivedExample (still finding factors)
THAT'S COOL, BUT I DON'T USE SETTIMEOUT OR WRITE
FUNCTIONS THAT DO HEAVY COMPUTATION.
A SEQUENCE OF USER EVENTS ARE ASYNCHRONOUS BY
NATURE.
But more importantly...

THE FIRST 'A' IN 'AJAX'
IS 'ASYNCHRONOUS'
(The 'X' in 'Ajax' is 'XML', but we'll ignore that)
fnto laSuf){
ucin odtf(
vrxr=nwXLtpeus(;
a h
e MHtRqet)
xrorayttcag =fnto( {
h.nedsaehne
ucin)
i(h.edSae==4 {
fxrraytt = )
cnoelgxrrsosTx)
osl.o(h.epneet;
}
}
xroe(GT,'di?ea=';
h.pn'E' /otdly5)
xrsn(;
h.ed)
cnoelg"eus sn!)
osl.o(Rqet et";
}
laSuf)
odtf(;
YOU CAN'T WRITE ASYNCHRONOUS CODE SYNCHRONOUSLY
fnto gttf( {
ucin eSuf)
vrxr=nwXLtpeus(;
a h
e MHtRqet)
vrrsls
a eut;
xrorayttcag =fnto( {
h.nedsaehne
ucin)
i(h.edSae==4 {
fxrraytt = )
rsls=xrrsosTx;
eut
h.epneet
}
}
xroe(GT,'di?ea=';
h.pn'E' /otdly5)
xrsn(;
h.ed)
rtr rsls
eun eut;
}
cnoelg"tf i " gttf()
osl.o(Suf s , eSuf);
YOU CAN MAKE SOME ASYNCHRONOUS CODE SYNCHRONOUS,
BUT EXECUTION WILL BLOCK ALL EVENTS
fnto gttf( {
ucin eSuf)
vrxr=nwXLtpeus(;
a h
e MHtRqet)
vrrsls
a eut;
xrorayttcag =fnto( {
h.nedsaehne
ucin)
i(h.edSae==4 {
fxrraytt = )
rsls=xrrsosTx;
eut
h.epneet
}
}
xroe(GT,'di?ea=' fle;/ tidprmi te'sn'prm
h.pn'E' /otdly5, as) / hr aa s h ayc aa
xrsn(;
h.ed)
rtr rsls
eun eut;
}
cnoelg"tf i " gttf()
osl.o(Suf s , eSuf);
HOW DO WE MAKE THE ASYNCHRONOUS CODE MORE
UNDERSTANDABLE?

CALLBACKS
fnto gttf(r,clbc){
ucin eSuful alak
vrxr=nwXLtpeus(;
a h
e MHtRqet)
xrorayttcag =fnto( {
h.nedsaehne
ucin)
i(h.edSae==4 {
fxrraytt = )
clbc(h.epneet;
alakxrrsosTx)
}
}
xroe(GT,ul;
h.pn'E' r)
xrsn(;
h.ed)
}
gttf(/otdly5,fnto(epne {
eSuf'di?ea=' ucinrsos)
cnoelgrsos)
osl.o(epne;
};
)
BUT WHAT IF I NEED TO DO THINGS THAT DEPEND ON EACH
OTHER?
gttf(/srcret,fnto(eut {
eSuf'ue/urn' ucinrsl)
vrueNm =gtaermeutrsl)
a srae
eNmFoRsl(eut;
cnoelg"el,"+ueNm)
osl.o(Hlo
srae;
vrmsaeR =gtesgUIrmeutrsl)
a esgUI
eMsaeRFoRsl(eut;
gttf(esgUI fnto(esgs {
eSufmsaeR, ucinmsae)
vrmsaeon =gtesgCutrmeutmsae)
a esgCut
eMsaeonFoRsl(esgs;
cnoelg
osl.o(
"o hv "+msaeon +"msae.)
Yu ae
esgCut
esgs";
};
)
};
)
WHAT ABOUT (*GASP*) ERRORS?
gttf(/srcret,fnto(eut {
eSuf'ue/urn' ucinrsl)
vrueNm =gtaermeutrsl)
a srae
eNmFoRsl(eut;
cnoelg"el,"+ueNm)
osl.o(Hlo
srae;
vrmsaeR =gtesgUIrmeutrsl)
a esgUI
eMsaeRFoRsl(eut;
gttf(esgUI fnto(esgs {
eSufmsaeR, ucinmsae)
vrmsaeon =gtesgCutrmeutmsae)
a esgCut
eMsaeonFoRsl(esgs;
cnoelg
osl.o(
"o hv "+msaeon +"msae.)
Yu ae
esgCut
esgs";
} fnto(r){
, uciner
cnoelg
osl.o(
"nerrocre gtigmsae:,ermsae;
A ro curd etn esgs" r.esg)
};
)
} fnto(r){
, uciner
cnoelg
osl.o(
"nerrocre gtigue dt:,ermsae;
A ro curd etn sr aa" r.esg)
};
)
gttf(/srcret,fnto(h,er {
eSuf'ue/urn' ucinxr r)
i(r){
fer
cnoelg
osl.o(
"nerrocre gtigue dt:,ermsae;
A ro curd etn sr aa" r.esg)
}
vrueNm =gtaermeutrsls;
a srae
eNmFoRsl(eut)
cnoelg"el,"+ueNm)
osl.o(Hlo
srae;
vrmsaeR =gtesgUIrmeutrsls;
a esgUI
eMsaeRFoRsl(eut)
gttf(esgUI fnto(esgs er {
eSufmsaeR, ucinmsae, r)
i(r){
fer
cnoelg
osl.o(
"nerrocre gtigmsae:,ermsae
A ro curd etn esgs" r.esg)
}
vrmsaeon =gtesgCutrmeutmsae)
a esgCut
eMsaeonFoRsl(esgs;
cnoelg
osl.o(
"o hv "+msaeon +"msae.)
Yu ae
esgCut
esgs";
};
)
};
)
GOOD THINGS WITH THIS APPROACH?
Understandable
Easy to consume
Direct API
PROBLEMS WITH THIS APPROACH?
Readability
Testing
Tight coupling / Wrong direction of dependencies
Pyramid of doom
HOW CAN WE ADDRESS THESE PROBLEMS?
CAN WE MANAGE ASYNCHRONOUS PROCESSES BY SHARING
AN OBJECT BETWEEN THE CONSUMER AND THE PRODUCER?
Consumer -> Shared Object <- Producer
fnto gttfASaeOjc(r){
ucin eSufshrdbetul
vrxr=nwXLtpeus(;
a h
e MHtRqet)
vrsae ={
a hrd
rsls
eut:
nl
ul
}
;
xrorayttcag =fnto( {
h.nedsaehne
ucin)
i(h.edSae==4 {
fxrraytt = )
sae.eut =xrrsosTx;
hrdrsls
h.epneet
}
}
xroe(GT,ul;
h.pn'E' r)
xrsn(;
h.ed)
rtr sae;
eun hrd
}
fnto cetSaeHnlrsae){
ucin raehrdade(hrd
vrhnlr=fnto( {
a ade
ucin)
i(sae.eut){
f!hrdrsls
stieu(ade,
eTmothnlr
}
es {
le
cnoelgsae.eut)
osl.o(hrdrsls;
}
}
rtr hnlr
eun ade;
}

0;
)

vrsae =gttfASaeOjc(di?ea=';
a hrd
eSufshrdbet'otdly5)
cetSaeHnlrsae))
raehrdade(hrd(;
Create an object in a producer that can be told that processing
is done
Get an object from the producer to the consumer so that the
consumer can tell it to do something
fnto gttfWtCodntrul {
ucin eSufihoriao(r)
vrxr=nwXLtpeus(;
a h
e MHtRqet)
vrcodntr=nwCodntr)
a oriao
e oriao(;
xrorayttcag =fnto( {
h.nedsaehne
ucin)
i(h.edSae==4 {
fxrraytt = )
codntraloenTeaasxrrsosTx)
oriao.lDnAdhDtI(h.epneet;
}
}
xroe(GT,ul;
h.pn'E' r)
xrsn(;
h.ed)
rtr codntrcnueOjc(;
eun oriao.osmrbet)
}
gttfWtCodntr'ue/urn'
eSufihoriao(/srcret)
.nTe(ucinrsl){
adhnfnto(eut
vrueNm =gtaermeutrsl)
a srae
eNmFoRsl(eut;
cnoelg"el,"+ueNm)
osl.o(Hlo
srae;
vrmsaeR =gtesgUIrmeutrsl)
a esgUI
eMsaeRFoRsl(eut;
rtr gttfWtCodntrmsaeR)
eun eSufihoriao(esgUI;
}.nTe(ucinrsl){
)adhnfnto(eut
vrmsaeon =gtesgCutrmeutrsl)
a esgCut
eMsaeonFoRsl(eut;
cnoelg"o hv "+msaeon +"msae.)
osl.o(Yu ae
esgCut
esgs";
};
)
fnto Codntr){
ucin oriao(
vrclbcs=[;
a alak
]
vrecpinades=[;
a xetoHnlr
]
rtr {
eun
aloenTeaas
lDnAdhDtI:
fnto(aa {
ucindt)
frvri=0 i<clbcslnt;i+ {
o(a
;
alak.egh +)
clbcsi(aa;
alak[]dt)
}
}
,
tigSrwdp
hnsceeU:
fnto(x {
ucine)
frvri=0 i<clbcslnt;i+ {
o(a
;
alak.egh +)
ecpinadesi(x;
xetoHnlr[]e)
}
}
,
cnueOjc:
osmrbet
fnto( {
ucin)
rtr {
eun
adhn
nTe:
fnto(n er {
ucinf, r)
vrcodntr=Codntr)
a oriao
oriao(;
vrclbc =fnto( {
a alak
ucin)
rsl.nTe(oriao.lDnAdhDtI,codntrtigSrwdp;
eutadhncodntraloenTeaas oriao.hnsceeU)
clbcsps(alak;
alak.uhclbc)
rtr codntrcnueOjc(;
eun oriao.osmrbet)
}
}
}
}
}
PROMISE
PROMISES/A+
A spec that builds out a standard for asynchronous
communication using a shared communication object called a
promise.
SO YOU TURNED NESTED CALLBACKS INTO A CHAIN.

BIG WHOOP!
A promise represents the future value that will be returned.
fnto gttfAPoieul {
ucin eSufsrms(r)
vrxr=nwXLtpeus(;
a h
e MHtRqet)
vrdfre =Qdfr)
a eerd
.ee(;
xrorayttcag =fnto( {
h.nedsaehne
ucin)
i(h.edSae==4 {
fxrraytt = )
i(h.ttsoe==50 {
fxrsauCd = 0)
trw"oehn poe o tesre!;
ho Smtig opd n h evr"
}
es {
le
dfre.eov(SNprexrrsosTx);
eerdrsleJO.as(h.epneet)
}
}
}
xroe(GT,ul;
h.pn'E' r)
xrsn(;
h.ed)
rtr dfre.rms;
eun eerdpoie
}
fnto gtsrnosrms( {
ucin eUeIfAPoie)
rtr gttfAPoie'ue/urn'
eun eSufsrms(/srcret)
.hn
te(
fnto(aa {
ucindt)
cnoelg
osl.o(
"el," dt.ae;
Hlo , aanm)
rtr dt;
eun aa
};
)
}
fnto gtesgssrms(aa {
ucin eMsaeAPoiedt)
rtr gttfAPoiedt.esgUI.hnfnto(aa {
eun eSufsrms(aamsaeR)te(ucindt)
cnoelg
osl.o(
"o hv" dt.esgslnt,"esgs";
Yu ae, aamsae.egh msae.)
rtr dt;
eun aa
};
)
}
Qfalgtsrnosrms)
.cl(eUeIfAPoie
.hngtesgssrms)
te(eMsaeAPoie;
EXCEPTION HANDLING
fnto gtro( {
ucin eErr)
trw"hsi!;
ho O ht"
}
Qfalgtro()
.cl(eErr)
.hngtsrnosrms)
te(eUeIfAPoie
.hngtesgssrms)
te(eMsaeAPoie
.ac(uciner {
cthfnto(r)
cnoelger;
osl.o(r)
};
)
COMPOSITION
fnto mprmsspoie,f){
ucin aPoie(rmss n
rtr Qalpoie)te(ucinrsls {
eun .l(rmss.hnfnto(eut)
vrmpeRsls=[;
a apdeut
]
frvri=0 i<rslslnt;i+ {
o(a
;
eut.egh +)
mpeRslsps(nrslsi);
apdeut.uhf(eut[])
}
rtr mpeRsls
eun apdeut;
};
)
}
fnto srPoie(rmss {
ucin otrmsspoie)
fnto gtaarsl){
ucin eDt(eut
rtr pren(eutdt,1)
eun asItrsl.aa 0;
}
rtr mprmsspoie,gtaa.hnfnto(eut){
eun aPoie(rmss eDt)te(ucinrsls
rtr rslssr(;
eun eut.ot)
};
)
}
fnto stp){
ucin eU(
vrdt =[;
a aa
]
frvri=0 i<1;i+ {
o(a
;
0 +)
dt.uhgttfAPoie
aaps(eSufsrms(
}

'otx'+i)
di?=
);

srPoie(aa.hnfnto(otd {
otrmssdt)te(ucinsre)
frvri=0 i<sre.egh i+ {
o(a
;
otdlnt; +)
cnoelgsre[];
osl.o(otdi)
}
};
)
Promises are more than just a fancy callback system. A promise
stands in place of a future value.
When an object is "thenable", the value can be retrieved in the
future and used directly, making asynchronous concepts look
synchronous.
GOOD THINGS WITH THIS APPROACH
Code is much more flat
Easier to test
We can compose functions that take promises
We can handle exceptions very clearly
We can pass around promises as though they were the actual
value, using .then() to get the result
BAD THINGS WITH THIS APPROACH
Tends to cause some confusion because the abstraction isn't
straightforward
Using this in a public API is considered very opinionated, and
forces consumers of your API to use a specific paradigm
Multiple implementations of this, not all meet the standard
(*cough* jQuery *cough*)
RECAP
Asynchronous processes in JavaScript are handled with
callbacks.
Callback mechanisms introduce some problems such as error
handling, composition, testing.
Callbacks are functions, which are first class objects.
Instead of callbacks, what if we used a different object that
mediates between consumer and producer?
Promise objects are a type of mediator that represent the
future value of an async process.
Promises/A+ is an open standard with a specification.
Promise objects can be used in place of actual values to make
asynchronous code look synchronous.
QUESTIONS?

More Related Content

Similar to Asynchronous java script

2013-02-21 - .NET UG Rhein-Neckar: JavaScript Best Practices
2013-02-21 - .NET UG Rhein-Neckar: JavaScript Best Practices2013-02-21 - .NET UG Rhein-Neckar: JavaScript Best Practices
2013-02-21 - .NET UG Rhein-Neckar: JavaScript Best Practices
Johannes Hoppe
 
Creating windows store java script apps
Creating windows store java script appsCreating windows store java script apps
Creating windows store java script apps
Eugene Zharkov
 
How to create a 3.2 billion dollar business in 20 minutes: combining AngularJ...
How to create a 3.2 billion dollar business in 20 minutes: combining AngularJ...How to create a 3.2 billion dollar business in 20 minutes: combining AngularJ...
How to create a 3.2 billion dollar business in 20 minutes: combining AngularJ...
Ari Lerner
 
Presenting Seq for Node.js
Presenting Seq for Node.jsPresenting Seq for Node.js
Presenting Seq for Node.js
Douglas Muth
 
JavaScript pitfalls
JavaScript pitfallsJavaScript pitfalls
JavaScript pitfalls
Claudio Cicali
 
JavaFX, because you're worth it
JavaFX, because you're worth itJavaFX, because you're worth it
JavaFX, because you're worth it
Thierry Wasylczenko
 
Arquillian - extensions which you have to take with you to a deserted island
Arquillian - extensions which you have to take with you to a deserted islandArquillian - extensions which you have to take with you to a deserted island
Arquillian - extensions which you have to take with you to a deserted island
SoftwareMill
 
Flow of events during Media Player creation in Android
Flow of events during Media Player creation in AndroidFlow of events during Media Player creation in Android
Flow of events during Media Player creation in Android
Somenath Mukhopadhyay
 
nescala 2013
nescala 2013nescala 2013
nescala 2013
Hung Lin
 
Refactoring to symfony components
Refactoring to symfony componentsRefactoring to symfony components
Refactoring to symfony components
Michael Peacock
 
Build a compiler in 2hrs - NCrafts Paris 2015
Build a compiler in 2hrs -  NCrafts Paris 2015Build a compiler in 2hrs -  NCrafts Paris 2015
Build a compiler in 2hrs - NCrafts Paris 2015
Phillip Trelford
 
Introduction to ATS plugins
Introduction to ATS pluginsIntroduction to ATS plugins
Introduction to ATS plugins
PSUdaemon
 
More on Lex
More on LexMore on Lex
More on Lex
Tech_MX
 
Macroprocessor
MacroprocessorMacroprocessor
Macroprocessor
ksanthosh
 
Proxy OOP Pattern in PHP
Proxy OOP Pattern in PHPProxy OOP Pattern in PHP
Proxy OOP Pattern in PHP
Marco Pivetta
 
C++ Lambda and concurrency
C++ Lambda and concurrencyC++ Lambda and concurrency
C++ Lambda and concurrency
명신 김
 
A Backbone.js Tutorial for the Impatient - Part 1
A Backbone.js Tutorial for the Impatient - Part 1A Backbone.js Tutorial for the Impatient - Part 1
A Backbone.js Tutorial for the Impatient - Part 1
jsalonen Salonen
 
Area, surface &amp; volume
Area, surface &amp; volumeArea, surface &amp; volume
Area, surface &amp; volume
Zahidul Islam
 
Linq introduction
Linq introductionLinq introduction
Linq introduction
Mohammad Alyan
 
Advanced QUnit - Front-End JavaScript Unit Testing
Advanced QUnit - Front-End JavaScript Unit TestingAdvanced QUnit - Front-End JavaScript Unit Testing
Advanced QUnit - Front-End JavaScript Unit Testing
Lars Thorup
 

Similar to Asynchronous java script (20)

2013-02-21 - .NET UG Rhein-Neckar: JavaScript Best Practices
2013-02-21 - .NET UG Rhein-Neckar: JavaScript Best Practices2013-02-21 - .NET UG Rhein-Neckar: JavaScript Best Practices
2013-02-21 - .NET UG Rhein-Neckar: JavaScript Best Practices
 
Creating windows store java script apps
Creating windows store java script appsCreating windows store java script apps
Creating windows store java script apps
 
How to create a 3.2 billion dollar business in 20 minutes: combining AngularJ...
How to create a 3.2 billion dollar business in 20 minutes: combining AngularJ...How to create a 3.2 billion dollar business in 20 minutes: combining AngularJ...
How to create a 3.2 billion dollar business in 20 minutes: combining AngularJ...
 
Presenting Seq for Node.js
Presenting Seq for Node.jsPresenting Seq for Node.js
Presenting Seq for Node.js
 
JavaScript pitfalls
JavaScript pitfallsJavaScript pitfalls
JavaScript pitfalls
 
JavaFX, because you're worth it
JavaFX, because you're worth itJavaFX, because you're worth it
JavaFX, because you're worth it
 
Arquillian - extensions which you have to take with you to a deserted island
Arquillian - extensions which you have to take with you to a deserted islandArquillian - extensions which you have to take with you to a deserted island
Arquillian - extensions which you have to take with you to a deserted island
 
Flow of events during Media Player creation in Android
Flow of events during Media Player creation in AndroidFlow of events during Media Player creation in Android
Flow of events during Media Player creation in Android
 
nescala 2013
nescala 2013nescala 2013
nescala 2013
 
Refactoring to symfony components
Refactoring to symfony componentsRefactoring to symfony components
Refactoring to symfony components
 
Build a compiler in 2hrs - NCrafts Paris 2015
Build a compiler in 2hrs -  NCrafts Paris 2015Build a compiler in 2hrs -  NCrafts Paris 2015
Build a compiler in 2hrs - NCrafts Paris 2015
 
Introduction to ATS plugins
Introduction to ATS pluginsIntroduction to ATS plugins
Introduction to ATS plugins
 
More on Lex
More on LexMore on Lex
More on Lex
 
Macroprocessor
MacroprocessorMacroprocessor
Macroprocessor
 
Proxy OOP Pattern in PHP
Proxy OOP Pattern in PHPProxy OOP Pattern in PHP
Proxy OOP Pattern in PHP
 
C++ Lambda and concurrency
C++ Lambda and concurrencyC++ Lambda and concurrency
C++ Lambda and concurrency
 
A Backbone.js Tutorial for the Impatient - Part 1
A Backbone.js Tutorial for the Impatient - Part 1A Backbone.js Tutorial for the Impatient - Part 1
A Backbone.js Tutorial for the Impatient - Part 1
 
Area, surface &amp; volume
Area, surface &amp; volumeArea, surface &amp; volume
Area, surface &amp; volume
 
Linq introduction
Linq introductionLinq introduction
Linq introduction
 
Advanced QUnit - Front-End JavaScript Unit Testing
Advanced QUnit - Front-End JavaScript Unit TestingAdvanced QUnit - Front-End JavaScript Unit Testing
Advanced QUnit - Front-End JavaScript Unit Testing
 

Recently uploaded

Monitoring and Managing Anomaly Detection on OpenShift.pdf
Monitoring and Managing Anomaly Detection on OpenShift.pdfMonitoring and Managing Anomaly Detection on OpenShift.pdf
Monitoring and Managing Anomaly Detection on OpenShift.pdf
Tosin Akinosho
 
CAKE: Sharing Slices of Confidential Data on Blockchain
CAKE: Sharing Slices of Confidential Data on BlockchainCAKE: Sharing Slices of Confidential Data on Blockchain
CAKE: Sharing Slices of Confidential Data on Blockchain
Claudio Di Ciccio
 
Driving Business Innovation: Latest Generative AI Advancements & Success Story
Driving Business Innovation: Latest Generative AI Advancements & Success StoryDriving Business Innovation: Latest Generative AI Advancements & Success Story
Driving Business Innovation: Latest Generative AI Advancements & Success Story
Safe Software
 
Cosa hanno in comune un mattoncino Lego e la backdoor XZ?
Cosa hanno in comune un mattoncino Lego e la backdoor XZ?Cosa hanno in comune un mattoncino Lego e la backdoor XZ?
Cosa hanno in comune un mattoncino Lego e la backdoor XZ?
Speck&Tech
 
Infrastructure Challenges in Scaling RAG with Custom AI models
Infrastructure Challenges in Scaling RAG with Custom AI modelsInfrastructure Challenges in Scaling RAG with Custom AI models
Infrastructure Challenges in Scaling RAG with Custom AI models
Zilliz
 
“I’m still / I’m still / Chaining from the Block”
“I’m still / I’m still / Chaining from the Block”“I’m still / I’m still / Chaining from the Block”
“I’m still / I’m still / Chaining from the Block”
Claudio Di Ciccio
 
Generating privacy-protected synthetic data using Secludy and Milvus
Generating privacy-protected synthetic data using Secludy and MilvusGenerating privacy-protected synthetic data using Secludy and Milvus
Generating privacy-protected synthetic data using Secludy and Milvus
Zilliz
 
How to Get CNIC Information System with Paksim Ga.pptx
How to Get CNIC Information System with Paksim Ga.pptxHow to Get CNIC Information System with Paksim Ga.pptx
How to Get CNIC Information System with Paksim Ga.pptx
danishmna97
 
How to use Firebase Data Connect For Flutter
How to use Firebase Data Connect For FlutterHow to use Firebase Data Connect For Flutter
How to use Firebase Data Connect For Flutter
Daiki Mogmet Ito
 
20240607 QFM018 Elixir Reading List May 2024
20240607 QFM018 Elixir Reading List May 202420240607 QFM018 Elixir Reading List May 2024
20240607 QFM018 Elixir Reading List May 2024
Matthew Sinclair
 
“Building and Scaling AI Applications with the Nx AI Manager,” a Presentation...
“Building and Scaling AI Applications with the Nx AI Manager,” a Presentation...“Building and Scaling AI Applications with the Nx AI Manager,” a Presentation...
“Building and Scaling AI Applications with the Nx AI Manager,” a Presentation...
Edge AI and Vision Alliance
 
Taking AI to the Next Level in Manufacturing.pdf
Taking AI to the Next Level in Manufacturing.pdfTaking AI to the Next Level in Manufacturing.pdf
Taking AI to the Next Level in Manufacturing.pdf
ssuserfac0301
 
Building Production Ready Search Pipelines with Spark and Milvus
Building Production Ready Search Pipelines with Spark and MilvusBuilding Production Ready Search Pipelines with Spark and Milvus
Building Production Ready Search Pipelines with Spark and Milvus
Zilliz
 
Fueling AI with Great Data with Airbyte Webinar
Fueling AI with Great Data with Airbyte WebinarFueling AI with Great Data with Airbyte Webinar
Fueling AI with Great Data with Airbyte Webinar
Zilliz
 
Unlock the Future of Search with MongoDB Atlas_ Vector Search Unleashed.pdf
Unlock the Future of Search with MongoDB Atlas_ Vector Search Unleashed.pdfUnlock the Future of Search with MongoDB Atlas_ Vector Search Unleashed.pdf
Unlock the Future of Search with MongoDB Atlas_ Vector Search Unleashed.pdf
Malak Abu Hammad
 
Climate Impact of Software Testing at Nordic Testing Days
Climate Impact of Software Testing at Nordic Testing DaysClimate Impact of Software Testing at Nordic Testing Days
Climate Impact of Software Testing at Nordic Testing Days
Kari Kakkonen
 
HCL Notes und Domino Lizenzkostenreduzierung in der Welt von DLAU
HCL Notes und Domino Lizenzkostenreduzierung in der Welt von DLAUHCL Notes und Domino Lizenzkostenreduzierung in der Welt von DLAU
HCL Notes und Domino Lizenzkostenreduzierung in der Welt von DLAU
panagenda
 
Columbus Data & Analytics Wednesdays - June 2024
Columbus Data & Analytics Wednesdays - June 2024Columbus Data & Analytics Wednesdays - June 2024
Columbus Data & Analytics Wednesdays - June 2024
Jason Packer
 
Microsoft - Power Platform_G.Aspiotis.pdf
Microsoft - Power Platform_G.Aspiotis.pdfMicrosoft - Power Platform_G.Aspiotis.pdf
Microsoft - Power Platform_G.Aspiotis.pdf
Uni Systems S.M.S.A.
 
GraphRAG for Life Science to increase LLM accuracy
GraphRAG for Life Science to increase LLM accuracyGraphRAG for Life Science to increase LLM accuracy
GraphRAG for Life Science to increase LLM accuracy
Tomaz Bratanic
 

Recently uploaded (20)

Monitoring and Managing Anomaly Detection on OpenShift.pdf
Monitoring and Managing Anomaly Detection on OpenShift.pdfMonitoring and Managing Anomaly Detection on OpenShift.pdf
Monitoring and Managing Anomaly Detection on OpenShift.pdf
 
CAKE: Sharing Slices of Confidential Data on Blockchain
CAKE: Sharing Slices of Confidential Data on BlockchainCAKE: Sharing Slices of Confidential Data on Blockchain
CAKE: Sharing Slices of Confidential Data on Blockchain
 
Driving Business Innovation: Latest Generative AI Advancements & Success Story
Driving Business Innovation: Latest Generative AI Advancements & Success StoryDriving Business Innovation: Latest Generative AI Advancements & Success Story
Driving Business Innovation: Latest Generative AI Advancements & Success Story
 
Cosa hanno in comune un mattoncino Lego e la backdoor XZ?
Cosa hanno in comune un mattoncino Lego e la backdoor XZ?Cosa hanno in comune un mattoncino Lego e la backdoor XZ?
Cosa hanno in comune un mattoncino Lego e la backdoor XZ?
 
Infrastructure Challenges in Scaling RAG with Custom AI models
Infrastructure Challenges in Scaling RAG with Custom AI modelsInfrastructure Challenges in Scaling RAG with Custom AI models
Infrastructure Challenges in Scaling RAG with Custom AI models
 
“I’m still / I’m still / Chaining from the Block”
“I’m still / I’m still / Chaining from the Block”“I’m still / I’m still / Chaining from the Block”
“I’m still / I’m still / Chaining from the Block”
 
Generating privacy-protected synthetic data using Secludy and Milvus
Generating privacy-protected synthetic data using Secludy and MilvusGenerating privacy-protected synthetic data using Secludy and Milvus
Generating privacy-protected synthetic data using Secludy and Milvus
 
How to Get CNIC Information System with Paksim Ga.pptx
How to Get CNIC Information System with Paksim Ga.pptxHow to Get CNIC Information System with Paksim Ga.pptx
How to Get CNIC Information System with Paksim Ga.pptx
 
How to use Firebase Data Connect For Flutter
How to use Firebase Data Connect For FlutterHow to use Firebase Data Connect For Flutter
How to use Firebase Data Connect For Flutter
 
20240607 QFM018 Elixir Reading List May 2024
20240607 QFM018 Elixir Reading List May 202420240607 QFM018 Elixir Reading List May 2024
20240607 QFM018 Elixir Reading List May 2024
 
“Building and Scaling AI Applications with the Nx AI Manager,” a Presentation...
“Building and Scaling AI Applications with the Nx AI Manager,” a Presentation...“Building and Scaling AI Applications with the Nx AI Manager,” a Presentation...
“Building and Scaling AI Applications with the Nx AI Manager,” a Presentation...
 
Taking AI to the Next Level in Manufacturing.pdf
Taking AI to the Next Level in Manufacturing.pdfTaking AI to the Next Level in Manufacturing.pdf
Taking AI to the Next Level in Manufacturing.pdf
 
Building Production Ready Search Pipelines with Spark and Milvus
Building Production Ready Search Pipelines with Spark and MilvusBuilding Production Ready Search Pipelines with Spark and Milvus
Building Production Ready Search Pipelines with Spark and Milvus
 
Fueling AI with Great Data with Airbyte Webinar
Fueling AI with Great Data with Airbyte WebinarFueling AI with Great Data with Airbyte Webinar
Fueling AI with Great Data with Airbyte Webinar
 
Unlock the Future of Search with MongoDB Atlas_ Vector Search Unleashed.pdf
Unlock the Future of Search with MongoDB Atlas_ Vector Search Unleashed.pdfUnlock the Future of Search with MongoDB Atlas_ Vector Search Unleashed.pdf
Unlock the Future of Search with MongoDB Atlas_ Vector Search Unleashed.pdf
 
Climate Impact of Software Testing at Nordic Testing Days
Climate Impact of Software Testing at Nordic Testing DaysClimate Impact of Software Testing at Nordic Testing Days
Climate Impact of Software Testing at Nordic Testing Days
 
HCL Notes und Domino Lizenzkostenreduzierung in der Welt von DLAU
HCL Notes und Domino Lizenzkostenreduzierung in der Welt von DLAUHCL Notes und Domino Lizenzkostenreduzierung in der Welt von DLAU
HCL Notes und Domino Lizenzkostenreduzierung in der Welt von DLAU
 
Columbus Data & Analytics Wednesdays - June 2024
Columbus Data & Analytics Wednesdays - June 2024Columbus Data & Analytics Wednesdays - June 2024
Columbus Data & Analytics Wednesdays - June 2024
 
Microsoft - Power Platform_G.Aspiotis.pdf
Microsoft - Power Platform_G.Aspiotis.pdfMicrosoft - Power Platform_G.Aspiotis.pdf
Microsoft - Power Platform_G.Aspiotis.pdf
 
GraphRAG for Life Science to increase LLM accuracy
GraphRAG for Life Science to increase LLM accuracyGraphRAG for Life Science to increase LLM accuracy
GraphRAG for Life Science to increase LLM accuracy
 

Asynchronous java script

  • 1. ASYNCHRONOUS JAVASCRIPT GET STUFF DONE BY KNOWING WHEN STUFF IS DONE.
  • 2. WANT TO HEAR A JAVASCRIPT JOKE? CALLBACK LATER AND I'LL TELL IT TO YA!
  • 3. CALLBACKS ARE HOW JAVASCRIPT MANAGES THINGS THAT NEED TO HAPPEN IN THE FUTURE fnto dlvrucln( { ucin eiePnhie) cnoelg"eas te tk tig ltrly"; osl.o(Bcue hy ae hns ieal.) } fnto stpoe){ ucin eUJk( cnoelg"h dntketmnaslk pn?) osl.o(Wy o' lpoaic ie us"; stieu(eiePnhie 20) eTmotdlvrucln, 00; } stpoe) eUJk(;
  • 4. EVENT PUMP setUpJoke deliverPunchline (after 2000 ms) EXECUTION THREAD setUpJoke deliverPunchline
  • 5. WHAT HAPPENS IF THE EXECUTION THREAD IS BUSY? fnto dlvrucln( { ucin eiePnhie) cnoelg"eas svnhssm bds ttos"; osl.o(Bcue ee a oe aas ato.) } fnto cnrvdxml( { ucin otieEape) cnoelg"h i sxari o svn"; osl.o(Wy s i fad f ee?) stieu(eiePnhie 20) eTmotdlvrucln, 00; fnPieatrFrETEEYLRENME) idrmFcoso(XRML_AG_UBR; } fnto cnrvdxml(; ucin otieEape)
  • 6. EVENT PUMP contrivedExample deliverPunchline in 2000 ms (2000 ms are up!) EXECUTION THREAD contrivedExample (still finding factors) deliverPunchline WAY after 2000 ms!
  • 7. IN JAVASCRIPT, EVENTS ARE BLOCKED BY CURRENTLY EXECUTING CODE.
  • 8. "In JavaScript, events are blocked by currently executing code." -RonTime
  • 9. " "In JavaScript, events are blocked by currently executing code." RonTime " -Your Name Here
  • 10. EVENT PUMP user furiously smashing keyboard event scroll event mouse click event deliverPunchline in 100 ms EXECUTION QUEUE contrivedExample (still finding factors)
  • 11. THAT'S COOL, BUT I DON'T USE SETTIMEOUT OR WRITE FUNCTIONS THAT DO HEAVY COMPUTATION.
  • 12. A SEQUENCE OF USER EVENTS ARE ASYNCHRONOUS BY NATURE.
  • 13. But more importantly... THE FIRST 'A' IN 'AJAX' IS 'ASYNCHRONOUS'
  • 14. (The 'X' in 'Ajax' is 'XML', but we'll ignore that)
  • 15. fnto laSuf){ ucin odtf( vrxr=nwXLtpeus(; a h e MHtRqet) xrorayttcag =fnto( { h.nedsaehne ucin) i(h.edSae==4 { fxrraytt = ) cnoelgxrrsosTx) osl.o(h.epneet; } } xroe(GT,'di?ea='; h.pn'E' /otdly5) xrsn(; h.ed) cnoelg"eus sn!) osl.o(Rqet et"; } laSuf) odtf(;
  • 16. YOU CAN'T WRITE ASYNCHRONOUS CODE SYNCHRONOUSLY fnto gttf( { ucin eSuf) vrxr=nwXLtpeus(; a h e MHtRqet) vrrsls a eut; xrorayttcag =fnto( { h.nedsaehne ucin) i(h.edSae==4 { fxrraytt = ) rsls=xrrsosTx; eut h.epneet } } xroe(GT,'di?ea='; h.pn'E' /otdly5) xrsn(; h.ed) rtr rsls eun eut; } cnoelg"tf i " gttf() osl.o(Suf s , eSuf);
  • 17. YOU CAN MAKE SOME ASYNCHRONOUS CODE SYNCHRONOUS, BUT EXECUTION WILL BLOCK ALL EVENTS fnto gttf( { ucin eSuf) vrxr=nwXLtpeus(; a h e MHtRqet) vrrsls a eut; xrorayttcag =fnto( { h.nedsaehne ucin) i(h.edSae==4 { fxrraytt = ) rsls=xrrsosTx; eut h.epneet } } xroe(GT,'di?ea=' fle;/ tidprmi te'sn'prm h.pn'E' /otdly5, as) / hr aa s h ayc aa xrsn(; h.ed) rtr rsls eun eut; } cnoelg"tf i " gttf() osl.o(Suf s , eSuf);
  • 18. HOW DO WE MAKE THE ASYNCHRONOUS CODE MORE UNDERSTANDABLE? CALLBACKS
  • 19. fnto gttf(r,clbc){ ucin eSuful alak vrxr=nwXLtpeus(; a h e MHtRqet) xrorayttcag =fnto( { h.nedsaehne ucin) i(h.edSae==4 { fxrraytt = ) clbc(h.epneet; alakxrrsosTx) } } xroe(GT,ul; h.pn'E' r) xrsn(; h.ed) } gttf(/otdly5,fnto(epne { eSuf'di?ea=' ucinrsos) cnoelgrsos) osl.o(epne; }; )
  • 20. BUT WHAT IF I NEED TO DO THINGS THAT DEPEND ON EACH OTHER?
  • 21. gttf(/srcret,fnto(eut { eSuf'ue/urn' ucinrsl) vrueNm =gtaermeutrsl) a srae eNmFoRsl(eut; cnoelg"el,"+ueNm) osl.o(Hlo srae; vrmsaeR =gtesgUIrmeutrsl) a esgUI eMsaeRFoRsl(eut; gttf(esgUI fnto(esgs { eSufmsaeR, ucinmsae) vrmsaeon =gtesgCutrmeutmsae) a esgCut eMsaeonFoRsl(esgs; cnoelg osl.o( "o hv "+msaeon +"msae.) Yu ae esgCut esgs"; }; ) }; )
  • 23. gttf(/srcret,fnto(eut { eSuf'ue/urn' ucinrsl) vrueNm =gtaermeutrsl) a srae eNmFoRsl(eut; cnoelg"el,"+ueNm) osl.o(Hlo srae; vrmsaeR =gtesgUIrmeutrsl) a esgUI eMsaeRFoRsl(eut; gttf(esgUI fnto(esgs { eSufmsaeR, ucinmsae) vrmsaeon =gtesgCutrmeutmsae) a esgCut eMsaeonFoRsl(esgs; cnoelg osl.o( "o hv "+msaeon +"msae.) Yu ae esgCut esgs"; } fnto(r){ , uciner cnoelg osl.o( "nerrocre gtigmsae:,ermsae; A ro curd etn esgs" r.esg) }; ) } fnto(r){ , uciner cnoelg osl.o( "nerrocre gtigue dt:,ermsae; A ro curd etn sr aa" r.esg) }; )
  • 24. gttf(/srcret,fnto(h,er { eSuf'ue/urn' ucinxr r) i(r){ fer cnoelg osl.o( "nerrocre gtigue dt:,ermsae; A ro curd etn sr aa" r.esg) } vrueNm =gtaermeutrsls; a srae eNmFoRsl(eut) cnoelg"el,"+ueNm) osl.o(Hlo srae; vrmsaeR =gtesgUIrmeutrsls; a esgUI eMsaeRFoRsl(eut) gttf(esgUI fnto(esgs er { eSufmsaeR, ucinmsae, r) i(r){ fer cnoelg osl.o( "nerrocre gtigmsae:,ermsae A ro curd etn esgs" r.esg) } vrmsaeon =gtesgCutrmeutmsae) a esgCut eMsaeonFoRsl(esgs; cnoelg osl.o( "o hv "+msaeon +"msae.) Yu ae esgCut esgs"; }; ) }; )
  • 25. GOOD THINGS WITH THIS APPROACH? Understandable Easy to consume Direct API
  • 26. PROBLEMS WITH THIS APPROACH? Readability Testing Tight coupling / Wrong direction of dependencies Pyramid of doom
  • 27. HOW CAN WE ADDRESS THESE PROBLEMS?
  • 28. CAN WE MANAGE ASYNCHRONOUS PROCESSES BY SHARING AN OBJECT BETWEEN THE CONSUMER AND THE PRODUCER?
  • 29. Consumer -> Shared Object <- Producer
  • 30. fnto gttfASaeOjc(r){ ucin eSufshrdbetul vrxr=nwXLtpeus(; a h e MHtRqet) vrsae ={ a hrd rsls eut: nl ul } ; xrorayttcag =fnto( { h.nedsaehne ucin) i(h.edSae==4 { fxrraytt = ) sae.eut =xrrsosTx; hrdrsls h.epneet } } xroe(GT,ul; h.pn'E' r) xrsn(; h.ed) rtr sae; eun hrd } fnto cetSaeHnlrsae){ ucin raehrdade(hrd vrhnlr=fnto( { a ade ucin) i(sae.eut){ f!hrdrsls stieu(ade, eTmothnlr } es { le cnoelgsae.eut) osl.o(hrdrsls; } } rtr hnlr eun ade; } 0; ) vrsae =gttfASaeOjc(di?ea='; a hrd eSufshrdbet'otdly5) cetSaeHnlrsae)) raehrdade(hrd(;
  • 31. Create an object in a producer that can be told that processing is done Get an object from the producer to the consumer so that the consumer can tell it to do something
  • 32. fnto gttfWtCodntrul { ucin eSufihoriao(r) vrxr=nwXLtpeus(; a h e MHtRqet) vrcodntr=nwCodntr) a oriao e oriao(; xrorayttcag =fnto( { h.nedsaehne ucin) i(h.edSae==4 { fxrraytt = ) codntraloenTeaasxrrsosTx) oriao.lDnAdhDtI(h.epneet; } } xroe(GT,ul; h.pn'E' r) xrsn(; h.ed) rtr codntrcnueOjc(; eun oriao.osmrbet) }
  • 33. gttfWtCodntr'ue/urn' eSufihoriao(/srcret) .nTe(ucinrsl){ adhnfnto(eut vrueNm =gtaermeutrsl) a srae eNmFoRsl(eut; cnoelg"el,"+ueNm) osl.o(Hlo srae; vrmsaeR =gtesgUIrmeutrsl) a esgUI eMsaeRFoRsl(eut; rtr gttfWtCodntrmsaeR) eun eSufihoriao(esgUI; }.nTe(ucinrsl){ )adhnfnto(eut vrmsaeon =gtesgCutrmeutrsl) a esgCut eMsaeonFoRsl(eut; cnoelg"o hv "+msaeon +"msae.) osl.o(Yu ae esgCut esgs"; }; )
  • 34. fnto Codntr){ ucin oriao( vrclbcs=[; a alak ] vrecpinades=[; a xetoHnlr ] rtr { eun aloenTeaas lDnAdhDtI: fnto(aa { ucindt) frvri=0 i<clbcslnt;i+ { o(a ; alak.egh +) clbcsi(aa; alak[]dt) } } , tigSrwdp hnsceeU: fnto(x { ucine) frvri=0 i<clbcslnt;i+ { o(a ; alak.egh +) ecpinadesi(x; xetoHnlr[]e) } } , cnueOjc: osmrbet fnto( { ucin) rtr { eun adhn nTe: fnto(n er { ucinf, r) vrcodntr=Codntr) a oriao oriao(; vrclbc =fnto( { a alak ucin) rsl.nTe(oriao.lDnAdhDtI,codntrtigSrwdp; eutadhncodntraloenTeaas oriao.hnsceeU) clbcsps(alak; alak.uhclbc) rtr codntrcnueOjc(; eun oriao.osmrbet) } } } } }
  • 36. PROMISES/A+ A spec that builds out a standard for asynchronous communication using a shared communication object called a promise.
  • 37. SO YOU TURNED NESTED CALLBACKS INTO A CHAIN. BIG WHOOP!
  • 38. A promise represents the future value that will be returned.
  • 39. fnto gttfAPoieul { ucin eSufsrms(r) vrxr=nwXLtpeus(; a h e MHtRqet) vrdfre =Qdfr) a eerd .ee(; xrorayttcag =fnto( { h.nedsaehne ucin) i(h.edSae==4 { fxrraytt = ) i(h.ttsoe==50 { fxrsauCd = 0) trw"oehn poe o tesre!; ho Smtig opd n h evr" } es { le dfre.eov(SNprexrrsosTx); eerdrsleJO.as(h.epneet) } } } xroe(GT,ul; h.pn'E' r) xrsn(; h.ed) rtr dfre.rms; eun eerdpoie }
  • 40. fnto gtsrnosrms( { ucin eUeIfAPoie) rtr gttfAPoie'ue/urn' eun eSufsrms(/srcret) .hn te( fnto(aa { ucindt) cnoelg osl.o( "el," dt.ae; Hlo , aanm) rtr dt; eun aa }; ) }
  • 41. fnto gtesgssrms(aa { ucin eMsaeAPoiedt) rtr gttfAPoiedt.esgUI.hnfnto(aa { eun eSufsrms(aamsaeR)te(ucindt) cnoelg osl.o( "o hv" dt.esgslnt,"esgs"; Yu ae, aamsae.egh msae.) rtr dt; eun aa }; ) }
  • 43. EXCEPTION HANDLING fnto gtro( { ucin eErr) trw"hsi!; ho O ht" } Qfalgtro() .cl(eErr) .hngtsrnosrms) te(eUeIfAPoie .hngtesgssrms) te(eMsaeAPoie .ac(uciner { cthfnto(r) cnoelger; osl.o(r) }; )
  • 44. COMPOSITION fnto mprmsspoie,f){ ucin aPoie(rmss n rtr Qalpoie)te(ucinrsls { eun .l(rmss.hnfnto(eut) vrmpeRsls=[; a apdeut ] frvri=0 i<rslslnt;i+ { o(a ; eut.egh +) mpeRslsps(nrslsi); apdeut.uhf(eut[]) } rtr mpeRsls eun apdeut; }; ) } fnto srPoie(rmss { ucin otrmsspoie) fnto gtaarsl){ ucin eDt(eut rtr pren(eutdt,1) eun asItrsl.aa 0; } rtr mprmsspoie,gtaa.hnfnto(eut){ eun aPoie(rmss eDt)te(ucinrsls rtr rslssr(; eun eut.ot) }; ) } fnto stp){ ucin eU( vrdt =[; a aa ] frvri=0 i<1;i+ { o(a ; 0 +) dt.uhgttfAPoie aaps(eSufsrms( } 'otx'+i) di?= ); srPoie(aa.hnfnto(otd { otrmssdt)te(ucinsre) frvri=0 i<sre.egh i+ { o(a ; otdlnt; +) cnoelgsre[]; osl.o(otdi) } }; )
  • 45. Promises are more than just a fancy callback system. A promise stands in place of a future value.
  • 46. When an object is "thenable", the value can be retrieved in the future and used directly, making asynchronous concepts look synchronous.
  • 47. GOOD THINGS WITH THIS APPROACH Code is much more flat Easier to test We can compose functions that take promises We can handle exceptions very clearly We can pass around promises as though they were the actual value, using .then() to get the result
  • 48. BAD THINGS WITH THIS APPROACH Tends to cause some confusion because the abstraction isn't straightforward Using this in a public API is considered very opinionated, and forces consumers of your API to use a specific paradigm Multiple implementations of this, not all meet the standard (*cough* jQuery *cough*)
  • 49. RECAP
  • 50. Asynchronous processes in JavaScript are handled with callbacks. Callback mechanisms introduce some problems such as error handling, composition, testing. Callbacks are functions, which are first class objects. Instead of callbacks, what if we used a different object that mediates between consumer and producer? Promise objects are a type of mediator that represent the future value of an async process. Promises/A+ is an open standard with a specification. Promise objects can be used in place of actual values to make asynchronous code look synchronous.