Bernameya asynkron di JavaScriptê de (Callback, Promise, RxJs)

Silav hemû. Sergey Omelnitsky di têkiliyê de ye. Demek berê min li ser bernamesaziya reaktîf mazûvaniya weşanek kir, li wir min di JavaScriptê de behsa asynkroniyê kir. Îro ez dixwazim li ser vê materyalê notan bikim.

Bernameya asynkron di JavaScriptê de (Callback, Promise, RxJs)

Lê berî ku em dest bi materyalê sereke bikin, pêdivî ye ku em têbînîyek destpêkê bikin. Ji ber vê yekê em bi pênaseyan dest pê bikin: stok û dorek çi ye?

Lod berhevokek e ku hêmanên wê li ser bingeha LIFO-ya paşîn, yekem-derve têne wergirtin

Mar berhevokek e ku hêmanên wê li ser bingeha FIFO-ya yekem-derve, yekem-derve têne wergirtin

Baş e, em berdewam bikin.

Bernameya asynkron di JavaScriptê de (Callback, Promise, RxJs)

JavaScript zimanek bernamesaziyê yek-têlek e. Ev tê wê wateyê ku bi tenê yek xêzek darvekirinê û yek stûnek heye ku fonksiyonên ji bo darvekirinê li ser têne rêz kirin. Ji ber vê yekê, JavaScript dikare di demekê de tenê yek operasyonê pêk bîne, dema ku operasyonên din dê li benda dora xwe li stikê bisekinin heya ku ew werin gazî kirin.

Call stack avahiyek daneyê ye ku, bi tenê, agahdariya li ser cîhê bernameya ku em lê ne tomar dike. Ger em derbasî fonksiyonek bibin, em têketina wê berbi jora stikê ve dikişînin. Dema ku em ji fonksiyonek vedigerin, em hêmana herî jorîn ji stikê derdixin û vedigerin cihê ku me jê re digot fonksiyonê. Ya ku stack dikare bike ev e. Û niha pirsek pir balkêş. Wê hingê asynkronî di JavasScriptê de çawa dixebite?

Bernameya asynkron di JavaScriptê de (Callback, Promise, RxJs)

Di rastiyê de, ji bilî stackê, gerok ji bo xebata bi navê WebAPI re rêzek taybetî heye. Fonksiyonên di vê rêzê de tenê piştî ku stêk bi tevahî were paqij kirin dê bi rêzê bêne darve kirin. Tenê piştî vê yekê ji bo darvekirinê ew ji rêzê têne avêtin ser stikê. Heke di vê gavê de bi kêmanî yek hêmanek li ser stikê hebe, wê hingê ew nikarin li stikê werin zêdekirin. Tam ji ber vê yekê ye ku bangkirina fonksiyonan ji hêla demê ve bi gelemperî di wextê de ne rast e, ji ber ku fonksiyon dema ku ew tije ye nikare ji dorê bigire heya stikê.

Ka em li mînaka jêrîn binêrin û dest bi pêkanîna wê ya gav-bi-gav bikin. Ka em jî bibînin ka di pergalê de çi dibe.

console.log('Hi');
setTimeout(function cb1() {
    console.log('cb1');
}, 5000);
console.log('Bye');

Bernameya asynkron di JavaScriptê de (Callback, Promise, RxJs)

1) Hîn tiştek diqewime. Konsolê gerokê zelal e, stûna bangê vala ye.

Bernameya asynkron di JavaScriptê de (Callback, Promise, RxJs)

2) Dûv re fermana konsolê.log('Hi') li stûna bangê tê zêdekirin.

Bernameya asynkron di JavaScriptê de (Callback, Promise, RxJs)

3) Û pêk hat

Bernameya asynkron di JavaScriptê de (Callback, Promise, RxJs)

4) Dûv re console.log('Silav') ji stoka bangê tê rakirin.

Bernameya asynkron di JavaScriptê de (Callback, Promise, RxJs)

5) Naha biçin fermana setTimeout (fonksiyona cb1 () {… }). Ew li stoka bangê tê zêdekirin.

Bernameya asynkron di JavaScriptê de (Callback, Promise, RxJs)

6) Fermana setTimeout (fonksiyona cb1() {… }) tê pêkanîn. Gerok demjimêrek ku beşek ji Web API-yê ye diafirîne. Ew ê jimartinê pêk bîne.

Bernameya asynkron di JavaScriptê de (Callback, Promise, RxJs)

7) Fermana setTimeout(function cb1() {... }) karê xwe qedandiye û ji qata bangê tê derxistin.

Bernameya asynkron di JavaScriptê de (Callback, Promise, RxJs)

8) Fermana konsol.log('Bye') li steka bangê tê zêdekirin.

Bernameya asynkron di JavaScriptê de (Callback, Promise, RxJs)

9) Fermana konsol.log('Bye') tê bicihanîn.

Bernameya asynkron di JavaScriptê de (Callback, Promise, RxJs)

10) Fermana konsolê.log('Bye') ji steka bangê tê derxistin.

Bernameya asynkron di JavaScriptê de (Callback, Promise, RxJs)

11) Piştî ku bi kêmî ve 5000 ms derbas bûn, demjimêr diqede û vegerandina cb1 di rêza vegerê de cîh dike.

Bernameya asynkron di JavaScriptê de (Callback, Promise, RxJs)

12) Kevirê bûyerê fonksiyona cb1 ji rêzika paşvekişandinê digire û li ser stûna bangê bi cih dike.

Bernameya asynkron di JavaScriptê de (Callback, Promise, RxJs)

13) Fonksîyona cb1 tê bicihanîn û console.log('cb1') li staka bangê zêde dike.

Bernameya asynkron di JavaScriptê de (Callback, Promise, RxJs)

14) Fermana konsolê.log('cb1') tê bicihkirin.

Bernameya asynkron di JavaScriptê de (Callback, Promise, RxJs)

15) Fermana konsolê.log('cb1') ji stûna bangê tê derxistin.

Bernameya asynkron di JavaScriptê de (Callback, Promise, RxJs)

16) Fonksîyona cb1 ji stûna bangê tê derxistin.

Ka em li mînakek dînamîk binêrin:

Bernameya asynkron di JavaScriptê de (Callback, Promise, RxJs)

Welê, me nihêrî ka asynkronî çawa di JavaScriptê de tête bicîh kirin. Naha em bi kurtî li ser pêşveçûna koda asynchronous biaxivin.

Pêşveçûna koda asynchronous.

a(function (resultsFromA) {
    b(resultsFromA, function (resultsFromB) {
        c(resultsFromB, function (resultsFromC) {
            d(resultsFromC, function (resultsFromD) {
                e(resultsFromD, function (resultsFromE) {
                    f(resultsFromE, function (resultsFromF) {
                        console.log(resultsFromF);
                    })
                })
            })
        })
    })
});

Bernamesaziya asynkron wekî ku em di JavaScriptê de dizanin tenê ji hêla fonksiyonan ve dikare were bicîh kirin. Ew dikarin mîna her guhêrbarek din derbasî fonksiyonên din bibin. Bi vî rengî bangawaziyan çêbû. Û ew sar, kêf û lîstik e, heya ku vedigere xemgînî, melankolî û xemgîniyê. Çima? Ew hêsan e:

  • Her ku tevlîheviya kodê zêde dibe, proje zû vediguhere blokên nezelal, çend caran hêlîn - "dojehê vegera bangê".
  • Desthilatdariya çewtiyê dikare hêsan be ku meriv ji bîr neke.
  • Tu nikarî bêjeyan bi vegerê vegerînî.

Bi hatina Sozê re rewş hinekî baştir bû.

new Promise(function(resolve, reject) {
    setTimeout(() => resolve(1), 2000);

}).then((result) => {
    alert(result);
    return result + 2;

}).then((result) => {
    throw new Error('FAILED HERE');
    alert(result);
    return result + 2;

}).then((result) => {
    alert(result);
    return result + 2;

}).catch((e) => {
    console.log('error: ', e);
});

  • Zencîreyên sozê xuya bûn, ku xwendina kodê çêtir kir
  • Rêbazek cihêreng ji bo girtina xeletiyan xuya bû
  • Ihtîmala darvekirina paralel bi karanîna Promise.all zêde kir
  • Em dikarin asynkroniya hêlînkirî bi karanîna async/bendê çareser bikin

Lê sozan kêmasiyên xwe hene. Mînakî, sozek bêyî reqsa bi tembûrê nayê betal kirin, û ya herî girîng ev e ku ew bi yek nirxê dixebite.

Welê, me bi rêkûpêk nêzîkê bernameya reaktîf kir. Westya? Welê, xwezî, hûn dikarin herin çayek çêkin, li ser bifikirin û vegerin da ku bêtir bixwînin. Û ez ê berdewam bikim.

Bernameya asynkron di JavaScriptê de (Callback, Promise, RxJs)

Bernamekirina reaktîf paradîgmayeke bernamesaziyê ye ku li ser herikîna daneyan û belavkirina guherînê ye. Werin em ji nêz ve binihêrin ka herikîna daneyê çi ye.

// Получаем ссылку на элемент
const input = ducument.querySelector('input');

const eventsArray = [];

// Пушим каждое событие в массив eventsArray
input.addEventListener('keyup',
    event => eventsArray.push(event)
);

Ka em bifikirin ku qada me ya têketinê heye. Em rêzek diafirînin û ji bo her keyupa bûyera têketinê em ê bûyerê di rêza xwe de hilînin. Di heman demê de, ez dixwazim bala xwe bidim ku rêzika me li gorî demê tê rêz kirin, ango. nîşaneya bûyerên paşerojê ji nîşaneya bûyerên berê mezintir e. Rêzeyek wusa modelek hêsankirî ya herikîna daneyê ye, lê ew hîn ne herikînek e. Ji bo ku ev array bi ewlehî wekî çemek were binav kirin, divê ew bi rengekî aboneyan agahdar bike ku daneyên nû tê de hatine. Bi vî awayî em tên ser pênaseya herikînê.

Herikîna daneyan

const { interval } = Rx;
const { take } = RxOperators;

interval(1000).pipe(
    take(4)
)

Bernameya asynkron di JavaScriptê de (Callback, Promise, RxJs)

Herrikîn komek daneyan e ku li gorî demê hatine rêz kirin ku dikare destnîşan bike ku dane hatine guhertin. Naha bifikire ku meriv çawa kodê dinivîse ku tê de yek çalakiyek hewceyê bangkirina çend bûyeran li beşên cihê yên kodê dike. Em bi tenê dibin abonetiya streamê û gava ku guhertin çêbibin ew ê me agahdar bike. Û pirtûkxaneya RxJs dikare vê yekê bike.

Bernameya asynkron di JavaScriptê de (Callback, Promise, RxJs)

RxJS pirtûkxaneyek e ji bo xebata bi bernameyên asynkron û-based bûyeran re bi karanîna rêzikên çavdêriyê. Pirtûkxane celebek bingehîn peyda dike Çavdêr, çend cureyên alîkar (Çavdêr, Bername, Mijar) û operatorên ji bo xebata bi bûyeran re wekî bi berhevokan (nexşe, parzûn, kêmkirin, her û yên mîna JavaScript Array).

Werin em têgehên bingehîn ên vê pirtûkxaneyê fam bikin.

Çavdêr, Çavdêr, Çêker

Observable yekem celebê bingehîn e ku em ê lê binêrin. Ev çîn beşa sereke ya pêkanîna RxJs dihewîne. Ew bi çemek çavdêrîkirî ve girêdayî ye, ku meriv dikare bi karanîna rêbaza abonetiyê were abone kirin.

Observable ji bo afirandina nûvekirinan mekanîzmayek arîkar pêk tîne, ku jê re tê gotin Çavdêr. Çavkaniya nirxan ji bo Çavdêr tê gotin Çêker. Ev dibe ku array, îterator, soketek malperê, celebek bûyer, hwd. Ji ber vê yekê em dikarin bibêjin ku observable di navbera Hilberîner û Çavdêr de rêgezek e.

Observable sê celeb bûyerên Observer digire:

  • paşê - daneyên nû
  • xelet - xeletiyek heke rêzik ji ber îstîsnayekê qediya. ev bûyer jî tê wateya temambûna rêzê.
  • temam - îşaretek li ser qedandina rêzê. Ev tê wê wateyê ku dê bêtir daneyên nû nebin.

Ka em demo bibînin:

Bernameya asynkron di JavaScriptê de (Callback, Promise, RxJs)

Di destpêkê de em ê nirxên 1, 2, 3, û piştî 1 saniyeyê pêvajo bikin. em ê 4 bi dest bixin û herika xwe biqedînin.

Bi dengekî bilind difikire

Û paşê min fêm kir ku vegotina wê ji nivîsandina wê balkêştir bû. 😀

Abonetî

Dema ku em bibin abone li streamek em çînek nû diafirînin endamêku ji me re şiyana betalkirina bi karanîna rêbazê dide me betal bike. Her weha em dikarin bi karanîna rêbazê aboneyan kom bikin lêzêdekirin. Welê, mentiqî ye ku em dikarin têlan bikar bînin kom bikin dûrxistin. Rêbazên lê zêdekirin û jêbirinê abonetiya din wekî têketinê qebûl dikin. Ez dixwazim bibînim ku gava em betal dikin, em ji hemî aboneyên zarokan vediqetin mîna ku wan gazî rêbaza betalkirinê kiriye. Berdewam bike.

Cureyên çeman

GERM
SARMA

Hilberîner li derveyî çavdêriyê tê afirandin
Hilberîner di hundurê çavdêriyê de tê afirandin

Dane di dema ku çavdêrî tê afirandin de têne veguheztin
Daneyên di dema abonetiyê de têne peyda kirin

Ji bo betalkirinê mentiqek din lazim e
Mijar bi serê xwe bi dawî dibe

Têkiliya yek-bi-gelek bikar tîne
Têkiliya yek bi yek bikar tîne

Hemî abonetî heman wateyê ne
Abonetî serbixwe ne

Heke abonetiya we tune be, dane dikarin winda bibin
Ji bo abonetiyek nû hemî nirxên streamê ji nû ve diweşîne

Ji bo ku ez mînaheviyek bidim, ez ê wekî fîlimek di şanoyê de fîlimek germ bifikirim. Tu di kîjan demê de hatî, ji wê gavê ve te dest bi temaşekirinê kir. Ez ê herikîna sar bi bangek teknolojiyê re bidim ber hev. alîkarî. Her bangewazî ji serî heya dawiyê guhê xwe dide tomarkirina posta dengî, lê hûn dikarin bi karanîna nebin abonetiyê telefonê biqedînin.

Ez dixwazim bibînim ku bi navê herikîna germ jî hene (ez bi vê pênaseyê pir kêm û tenê di civatên biyanî de rast hatim) - ev herikînek e ku ji herikîna sar vediguhere ya germ. Pirs derdikeve holê - li ku tê bikar anîn)) Ez ê mînakek ji pratîkê bidim.

Ez bi Angular re dixebitim. Ew bi awayekî çalak rxjs bikar tîne. Ji bo wergirtina daneyan ji serverê re, ez li bendê me têlek sar û vê mijarê di şablonê de bi karanîna asyncPipe bikar bînin. Ger ez vê boriyê çend caran bikar bînim, wê hingê, vegerim ser pênase çemek sar, her boriyek dê daneyan ji serverê bixwaze, ku bi kêmanî xerîb e. Û heke ez kaniyek sar veguherînim germek germ, wê hingê daxwaz dê carekê çêbibe.

Bi gelemperî, têgihîştina celebê herikandinê ji bo destpêkek pir dijwar e, lê girîng e.

Operators

return this.http.get(`${environment.apiUrl}/${this.apiUrl}/trade_companies`)
    .pipe(
        tap(({ data }: TradeCompanyList) => this.companies$$.next(cloneDeep(data))),
        map(({ data }: TradeCompanyList) => data)
    );

Operator ji me re kapasîteya ku em karîna xwe ya xebata bi çeman re berfireh bikin peyda dikin. Ew alîkariya kontrolkirina bûyerên ku di Observable de diqewimin dikin. Em ê çend ji yên herî populer binihêrin, û bêtir agahdarî di derbarê operatoran de dikarin bi karanîna girêdanên di agahdariya kêrhatî de werin dîtin.

Operators - ji

Ka em bi operatorê alîkar ya dest pê bikin. Ew li ser bingeha nirxek hêsan, Çavdêriyek diafirîne.

Bernameya asynkron di JavaScriptê de (Callback, Promise, RxJs)

Operators - Parzûna

Bernameya asynkron di JavaScriptê de (Callback, Promise, RxJs)

Operatorê fîlterê, wekî ku ji navê xwe diyar dike, sînyala herikê fîlter dike. Ger operator rast vegere, ew bêtir dişoxilîne.

Operator - bigirin

Bernameya asynkron di JavaScriptê de (Callback, Promise, RxJs)

bigire - Nirxa hejmara emitteran digire, piştî ku têl bi dawî dibe.

Operator - debounceTime

Bernameya asynkron di JavaScriptê de (Callback, Promise, RxJs)

debounceTime - nirxên belavkirî yên ku di navbeyna dema diyarkirî ya di navbera derkan de dikevin berdide - piştî ku navberê derbas dibe, nirxa paşîn derdixe.

const { Observable } = Rx;
const { debounceTime, take } = RxOperators;

Observable.create((observer) => {
  let i = 1;
  observer.next(i++);
  // Испускаем значение раз в 1000мс
  setInterval(() => {
    observer.next(i++)
  }, 1000);

 // Испускаем значение раз в 1500мс
  setInterval(() => {
    observer.next(i++)
  }, 1500);
}).pipe(
  debounceTime(700),  // Ожидаем 700мс значения прежде чем обработать
  take(3)
);  

Bernameya asynkron di JavaScriptê de (Callback, Promise, RxJs)

Operator - takeWhile

Bernameya asynkron di JavaScriptê de (Callback, Promise, RxJs)

Heya ku takeWhile derewîn vegerîne nirxan derdixe, piştî ku ew ji mijarê vediqete.

const { Observable } = Rx;
const { debounceTime, takeWhile } = RxOperators;

Observable.create((observer) => {
  let i = 1;
  observer.next(i++);
  // Испускаем значение раз в 1000мс
  setInterval(() => {
    observer.next(i++)
  }, 1000);
}).pipe(
  takeWhile( producer =>  producer < 5 )
);  

Bernameya asynkron di JavaScriptê de (Callback, Promise, RxJs)

Operator - combinationLatest

Operatora combineLatest hinekî dişibe soz.all. Ew gelek mijaran di yek de yek dike. Piştî ku her mijar bi kêmî ve yek emîsyonê çêdike, em ji her yekê di forma rêzek de nirxên herî dawî digirin. Wekî din, piştî her belavbûna ji çemên hevgirtî, ew ê nirxên nû bide.

Bernameya asynkron di JavaScriptê de (Callback, Promise, RxJs)

const { combineLatest, Observable } = Rx;
const { take } = RxOperators;

const observer_1 = Observable.create((observer) => {
  let i = 1;
  // Испускаем значение раз в 1000мс
  setInterval(() => {
    observer.next('a: ' + i++);
  }, 1000);
});

const observer_2 = Observable.create((observer) => {
  let i = 1;
  // Испускаем значение раз в 750мс
  setInterval(() => {
    observer.next('b: ' + i++);
  }, 750);
});

combineLatest(observer_1, observer_2).pipe(take(5));

Bernameya asynkron di JavaScriptê de (Callback, Promise, RxJs)

Operator - zip

Zip - Li benda nirxek ji her mijarê dimîne û li ser bingeha van nirxan rêzek çêdike. Heger nirx ji ti hêlekê dernekeve, wê demê kom çênabe.

Bernameya asynkron di JavaScriptê de (Callback, Promise, RxJs)

const { zip, Observable } = Rx;
const { take } = RxOperators;

const observer_1 = Observable.create((observer) => {
  let i = 1;
  // Испускаем значение раз в 1000мс
  setInterval(() => {
    observer.next('a: ' + i++);
  }, 1000);
});

const observer_2 = Observable.create((observer) => {
  let i = 1;
  // Испускаем значение раз в 750
  setInterval(() => {
    observer.next('b: ' + i++);
  }, 750);
});

const observer_3 = Observable.create((observer) => {
  let i = 1;
  // Испускаем значение раз в 500
  setInterval(() => {
    observer.next('c: ' + i++);
  }, 500);
});

zip(observer_1, observer_2, observer_3).pipe(take(5));

Bernameya asynkron di JavaScriptê de (Callback, Promise, RxJs)

Operator - forkJoin

forkJoin jî tevlî mijaran dibe, lê ew tenê dema ku hemî mijar temam bibin nirxek derdixe.

Bernameya asynkron di JavaScriptê de (Callback, Promise, RxJs)

const { forkJoin, Observable } = Rx;
const { take } = RxOperators;

const observer_1 = Observable.create((observer) => {
  let i = 1;
  // Испускаем значение раз в 1000мс
  setInterval(() => {
    observer.next('a: ' + i++);
  }, 1000);
}).pipe(take(3));

const observer_2 = Observable.create((observer) => {
  let i = 1;
  // Испускаем значение раз в 750
  setInterval(() => {
    observer.next('b: ' + i++);
  }, 750);
}).pipe(take(5));

const observer_3 = Observable.create((observer) => {
  let i = 1;
  // Испускаем значение раз в 500
  setInterval(() => {
    observer.next('c: ' + i++);
  }, 500);
}).pipe(take(4));

forkJoin(observer_1, observer_2, observer_3);

Bernameya asynkron di JavaScriptê de (Callback, Promise, RxJs)

Operator - nexşe

Operatorê veguherîna nexşeyê nirxa emitterê vediguherîne yekî nû.

Bernameya asynkron di JavaScriptê de (Callback, Promise, RxJs)

const {  Observable } = Rx;
const { take, map } = RxOperators;

Observable.create((observer) => {
  let i = 1;
  // Испускаем значение раз в 1000мс
  setInterval(() => {
    observer.next(i++);
  }, 1000);
}).pipe(
  map(x => x * 10),
  take(3)
);

Bernameya asynkron di JavaScriptê de (Callback, Promise, RxJs)

Operator - parve bikin, tap bikin

Operatorê tap destûrê dide we ku hûn bandorên alî bikin, ango, her kiryarên ku bandorê li rêzê nakin.

Operatorê karûbarê parvekirinê dikare kaniyek sar veguherîne germek.

Bernameya asynkron di JavaScriptê de (Callback, Promise, RxJs)

Em bi operatoran re qediyan. Ka em herin ser Mijar.

Bi dengekî bilind difikire

Û paşê ez çûm çayê vexwim. Ez ji van mînakan bêzar im 😀

Malbata mijarê

Malbata mijarê mînakek sereke ya herikîna germ e. Ev çîn celebek hîbrîdê ne ku di heman demê de wekî çavdêr û çavdêr tevdigerin. Ji ber ku mijar mijarek germ e, pêdivî ye ku meriv jê betal bibe. Ger em li ser rêbazên sereke biaxivin, wê hingê ev in:

  • paşê - veguheztina daneyên nû li ser çemê
  • xelet - xeletî û bidawîbûna mijarê
  • temam - temamkirina mijarê
  • bibin abone - bibin abone li herikekê
  • abonetiyê nekirin - ji herikînê veneqetin
  • asObservable - veguherîne çavdêrek
  • toPromise - vediguhere sozekê

4 5 cureyên mijaran hene.

Bi dengekî bilind difikire

Li ser çemê 4 kes dipeyivîn, lê derket holê ku wan yekî din lê zêde kiriye. Wekî ku dibêjin, bijîn û fêr bibin.

Mijara Hêsan new Subject()- cureya herî hêsan a mijaran. Bê pîvan hatine çêkirin. Nirxên ku tenê piştî abonetiyê hatine wergirtin vediguhezîne.

BehaviorSubject new BehaviorSubject( defaultData<T> ) - Bi dîtina min, mijara herî gelemperî ye. Input nirxa xwerû digire. Her gav daneyên jimareya paşîn, ya ku di dema abonetiyê de tê veguheztin, tomar dike. Ev çîn di heman demê de xwedan rêbazek nirxa kêrhatî ye, ku nirxa heyî ya tîrê vedigerîne.

ReplaySubject new ReplaySubject(bufferSize?: number, windowTime?: number) - Ketina vebijarkî dikare wekî argumana yekem mezinahiya tampona nirxan ku ew ê di xwe de hilîne, û wekî ya duyemîn dema ku tê de hewcedariya me bi guhertinan heye bigire.

AsyncSubject new AsyncSubject() - Di dema aboneyê de tiştek çênabe, û nirx tenê dema ku temam bibe dê were vegerandin. Tenê nirxa paşîn a herikê dê were vegerandin.

WebSocketSubject new WebSocketSubject(urlConfigOrSource: string | WebSocketSubjectConfig<T> | Observable<T>, destination?: Observer<T>) - Belge li ser wî bêdeng e û ez yekem car e ku wî dibînim. Ger kesek dizane ew çi dike, ji kerema xwe binivîse û em ê lê zêde bikin.

Phew. Welê, me her tiştê ku min dixwest îro ji we re bibêjim veşartiye. Ez hêvî dikim ku ev agahdarî kêrhatî bû. Hûn dikarin navnîşa referansan bixwe di tabloya agahdariya kêrhatî de bixwînin.

agahî alîkar

Source: www.habr.com

Add a comment