Video'yu izlemedim ama cevap gelmediği için şöyle bir yorum yapayım...
Promise kullanmasaydı ve request()
fonksiyonunu async
key'i ile tanımlasaydı da aynı işlemi yapabilirdi.
Promise kullanarak hangi durumda then()
veya hangi durumda catch()
bloğuna düşeceğini resolve()
ve reject()
fonksiyonlarıyla belirleyebildi.
request(url,data)
.then(result=>{
/* resolve() ile gönderilen result değeri buraya geldi */
})
.catch(result=>{
/* reject() ile gönderilen result değeri buraya geldi */
});
Peki aynı fonksiyonu Promise
olmadan yazsaydı?
function async request(url, data = false, method = 'GET') {
const options = {
method
}
if (data && method === 'POST') {
options.body = JSON.stringify(data)
}
const response = await fetch(url, options)
const result = await response.json();
if (response.ok && response.status === 200) {
return result;
} else {
throw result;
}
}
Böyle yazsaydık request()
fonksiyonunu şöyle kullanacaktık:
request(url,data)
.then(result=>{
/* return ile gönderilen result değeri buraya geldi */
})
.catch(result=>{
/* throw ile gönderilen result değeri buraya geldi */
});
Evet, Promise kullanmasa da olurmuş. :))
Belki fonksiyonu geliştirmeyi, anlamsal olarak ayrıştırmayı veya paralel istekler atabilme ihtimalini düşünmüştür ama sonra gerek kalmamıştır.
Mesela request()
fonksiyonunun paralel çalışacak 2 işlem yürütmesi gerekiyor ama bunların sadece birinin sonucunu alacak diyelim.
function request(url, data = false, method = 'GET') {
new Promise(async(resolve, reject) => {
setTimeout(()=>{ console.log("Ben de çalıştım!"); }, 4000);
});
return new Promise(async (resolve, reject) => {
const options = {
method
}
if (data && method === 'POST') {
options.body = JSON.stringify(data)
}
const response = await fetch(url, options)
const result = await response.json();
if (response.ok && response.status === 200) {
resolve(result)
} else {
reject(result)
}
})
}
Böylece request()
fonksiyonu çalıştığı anda ilk promise devreye girdi. Beklemeden 2.promise'ı return etti.
Tek fonksiyonda paralel iki işlem yürütmüş oldu. İlk promise 4 saniye sonra işlemini tamamlayacak. Ama request()
fonksiyonu mutlaka 2. promise'ın tamamlandığı zaman sonuç döndürecek.
Belki de sadece anlamsal olarak Promise kullanmak istemiş olabilir.
Yani request()
fonksiyonuna baktığı zaman burada asenkron bir işlem olduğunu anlamak Promise
adını görünce onun için daha hızlı şekilde anlaşılır oluyordur.
<div class="card">
<div class="imageSide">
<img src="https://picsum.photos/100" />
</div>
<div class="informationSide">
<div class="information">
<strong>120.235</strong>
<span>TAKİPÇİLER</span>
</div>
<div class="information">
<strong>120.235</strong>
<span>TAKİP EDİLEN</span>
</div>
</div>
</div>
.card, .card * {
display:flex;
margin:0;
padding:0;
flex-direction:column;
}
.card {
width:350px;
border:1px solid gray;
border-radius:10px;
background:#09c;
flex-direction:row;
align-items:center;
justify-content:space-between;
}
.card > .imageSide {
}
.card > .imageSide > img {
border-radius:50%;
width:100px;
margin:15px;
}
.card > .informationSide {
flex-direction:row;
flex-wrap: wrap;
align-items:center;
justify-content:flex-end;
margin-left:auto;
}
.card > .informationSide > .information {
width:100px;
text-align:center;
padding:5px 15px;
}
.card > .informationSide > .information > strong {
font-size:22px;
}
.card > .informationSide > .information > span {
font-size:12px;
}
.card
elementinin width
değerini artırdığınızda, takip elementlerinin yan yana geldiğini görebilirsiniz.
Bunu sağlayan flex tasarımda kullanılan flex-wrap
özelliğidir.
foreach içinde sql sorgusu atmamalısınız.
Hepsinde ortak olan sanırım orderId ve auth sütunları.
İlk sorgunuzdan sonra bu orderId ve auth değerlerini bir string içinde birleştirin ve or'larla birbirine bağlayın.
$detail = $this->connect->query("...");
$rowPD = $detail->rowCount();
$orderList = [];
$whereConditions = [];
$whereConditionsWithESD = [];
if ($rowPD > 0) {
$detail = $detail->fetchAll(PDO::FETCH_ASSOC);
foreach ($detail as $keys) {
$whereConditions[] = "(orderId='".$keys["orderId"]."' AND auth='".$this->appkey."')";
$whereConditionsWithESD[] = "(ESD.orderId='".$keys["orderId"]."' AND ESD.auth='".$this->appkey."')";
}
$whereCondition = implode(" OR ", $whereConditions);
$whereConditionWithESD = implode(" OR ", $whereConditionsWithESD);
$detail = $this->connect->query("... WHERE $whereCondition")->fetch(PDO::FETCH_ASSOC);
$adress = $this->connect->query("... WHERE $whereCondition")->fetchAll(PDO::FETCH_ASSOC);
$cargoDetail = $this->connect->query("... WHERE $whereCondition")->fetch(PDO::FETCH_ASSOC);
$customerDetail = $this->connect->query("... WHERE $whereCondition")->fetch(PDO::FETCH_ASSOC);
$list = $this->connect->query("... WHERE $whereConditionWithESD ...")->fetchAll(PDO::FETCH_ASSOC);
$orderList = [
"detail" => $detail,
"adress" => $adress,
"cargoDetail" => $cargoDetail,
"customerDetail" => $customerDetail,
"list" => $list
];
}
Sorgularınızın içeriğini bilmiyorum ama hepsinin WHERE koşulu aynı. sadece WHERE koşullarını yukarıdaki gibi düzenleyebilirsiniz.
Örneğin foreach içindeki ilk 4 sorgunuzdaki
where orderId='$orderId' and auth='$this->appkey'
yerine
WHERE $whereCondition
yazacaksınız.
$list
için olan son sorguda da
WHERE ESD.orderId = '$orderId' AND ESD.auth = '$this->appkey'
yerine
WHERE $whereConditionWithESD
yazacaksınız.
Böylece mesela $detail
için her foreach döngüsünde
WHERE orderId='123' auth='abc'
,
WHERE orderId='131' auth='abc'
,
WHERE orderId='213' auth='abc'
şeklinde yazıp istek atmadık da,
tek bir $detail
sorgusu için
WHERE (orderId='123' auth='abc') OR (orderId='131' auth='abc') OR (orderId='213' auth='abc')
şeklinde istek attık.
Yani mesela ilk sorgunuzdan 3 tane orderId döndüyse
foreach içindeki 5 sorgunuz 3 defa çalışacak ve MySQL'e 15 defa istek atacaksınız.
Yeni durumdaysa kaç tane orderId olursa olsun MySQL'e sadece 6 istek atacaksınız.
Veritabanına mümkün olduğunca az istek atılmalı. Bu işlem tek başına daha hızlı sonuç almanızı sağlayacaktır.
Eğer $list
sorgunuzda olduğu gibi diğer sorguları da tek sorguda birleştirme şansınız varsa çok daha iyi sonuç alırsınız.
MySQL ile mümkün olduğunca az bağlantı kurmalısınız.
NOT: bu işlem sonunca var_dump()
ile $orderList
değişkeninizi kontrol etmeniz gerekiyor. Çünkü sizin aldığınız json formatıyla bu yeni json formatı artık farklı. Ama her iki durumda da veritabanındaki aynı değerler artık elinizde.
Merhaba @262efe.
Input'tan aldığın değerler varsayılan olarak string türündedir. Input'tan gelen değerin sayı olup olmadığını isNaN()
fonksiyonuyla test edebilirsin. Sonra da Number()
fonksiyonuyla bu değeri sayıya çevirmelisin. Daha sonra işleme sokabilirsin. Eğer bölme işlemi yapacaksan bölen sayının sıfır olmadığına emin olmalısın çünkü sıfıra bölümler de NaN döner.
Input'tan aldığın verinin bir sayıyla çarpımıyla ilgili örnek:
<input id=userNumber type=number placeholder="Bir sayı girin" />
<button id=calculationButton>Hesapla</button>
<div id=resultArea></div>
// Butonu id attribute'si ile seçiyorum ve $calculationButton adlı değişkene atıyorum.
// Zorunlu değil ama bir elementi değişkene atıyorsak değişken adını $ işaretiyle başlatırız.
const $calculationButton = document.getElementById("calculationButton");
// input elementini de bir değişkene alıyorum.
const $userNumber = document.getElementById("userNumber");
// Sonucu yazacağımız div elementini de bir değişkene alıyorum.
const $resultArea = document.getElementById("resultArea");
// input'a girilen sayıyı hangi sayıyla çarpacağımızı da belirleyelim.
const constantNumber = 2;
// Butonun click olayını dinliyorum.
$calculationButton.addEventListener("click", function() {
// input'taki değeri bir değişkene alıyorum.
// Bu değişkenin değerini daha sonra değiştireceğim için const yerine let kullanarak oluşturuyorum.
let inputValue = $userNumber.value;
// Aldığım değerin sayı olup olmadığını kontrol ediyorum.
// Eğer sayı değilse bir uyarı verip işlem yapılmasını engelliyorum.
if(isNaN(inputValue)) {
$resultArea.innerHTML = "Bir sayı değeri girmelisiniz!"; // div'e uyarı mesajını yazdım.
$userNumber.value = ""; // Input'a yazılan değeri sildim.
return; // Bu fonksiyonun bu adımdan sonra çalışmamasını sağladım.
}
// Input sayısal değer içeren bir string'tir.
// Örneğin "12" bir string'tir ama tamamen sayılardan oluştuğu için
// isNaN() fonksiyonu bunun bir sayı olduğunu söyler. Biz bunu "12" değil 12 yapacağız:
inputValue = Number(inputValue);
// Artık güvenle çarpma işlemimizi yapabiliriz.
// Bölme işlemi yapmayacağımız için sayının 0 olup olmaması önemli değil.
// Sabit sayımız olan constantNumber ile input'un değeri olan inputValue'yi çarpabiliriz.
const result = constantNumber * inputValue;
// Bulduğum değeri resultArea id'li div elementine yazıyorum:
$resultArea.innerHTML = constantNumber + " x " + inputValue + " = " + result;
});
Mobil uygulama geliştirici olmak istiyorsanız, sırayla:
- İngilizce
- Javascript'i ilerletme, ES6, ES7, ES8, ES9, ES10...
- React Native
- TypeScript (ben sevmem)
Web geliştirici olmak istiyorsanız, sırayla:
- Html, css, javascript
- İngilizce
- Javascript'i ilerletme, ES6, ES7, ES8, ES9, ES10, ES11...
- React
- TypeScript
- Next.js
Mobil veya Web aşamalarından sonra sonra
- Express.js ile web servis geliştirme
- MySql veya MongoDb
- Redis
- Docker, Nginx
...
Neden React üzerinden yürüyoruz? Çünkü piyasaya hakim.
Svelte ile ilgili 1 iş, Vue ile ilgili 15 iş, Angular'la 20 iş, React ile ilgili 50 iş bulursunuz.
Mobil tarafta da Flutter ile 10 iş buluyorsanız React Native ile 50 iş bulursunuz.
Oranları uydurdum ama olay tamamen piyasa hakimiyeti. Bu hakimiyet hem Türkiye'de hem yurt dışında böyle. Uzun zaman da bu hakimiyet bozulmayacaktır. Bozulacak olsa Svelte gelir ve hepsini piyasadan silerdi. Deno gelir ve Javascript'i bitirirdi. Node.js gelir Apache'yi bitirirdi ve PHP projesi sonlanırdı. Bitirebildiler mi? Bitiremediler. Kolay kolay da bitiremezler.
Geçmişte piyasaya hakimiyet kurup da bir anda sonlanmış proje hiç yok mu? Var. Ama bu çok çok nadir yaşanan bir durum. Nitekim öldü bitti diye 10 yıldır yaygara koparılan PHP halen çok yaygın şekilde kullanılıyor.
1. Veriyi GET değil POST metoduyla gönderin.
2. Veriyi Cookie'ye kaydedin ve diğer sayfada cookie'den okuyun.
3. Veri sadece front-end'de kullanılacaksa sessionStorage'a kaydedin ve diğer sayfada da sessionStorage'dan okuyun.
4. Veriyi session yoluyla iletin.
5. GET ile gönderdiğiniz parametreleri şifreleyin ve diğer sayfada şifreyi çözün.
6. Verileri veritabanına kaydedin ve diğer sayfada veritabanını kontrol edin.
... aklıma gelenler bunlar.
Ama sizin yapmak istediğiniz şey, bir kullanıcı login olmuşsa bunu session'a kaydetmek ve index.php'de de session'ı kontrol etmek.
B sitesinin veritabanına bağlanma işini doğrudan B sitesinden erişerek yapabilirsiniz.
1. B sitesinde web servis gibi çalışacak bir sayfa oluşturun. Bu sayfa kendisine POST yöntemiyle gelen verileri alsın, kendi veritabanına yazsın.
2. A sitesinden bu B sitesindeki sayfaya POST isteği gönderin.
B sitesinde integration.php sayfası
$productId = $_POST["product_id"];
$newPrice = $_POST["price"];
updateDatabase("UPDATE products SET price='$newPrice' WHERE id=$productId");
echo json_encode(["status"=>true, "message"=>"Price updated successfully"]);
exit();
A sitesinde bir ürünün fiyatını kendi veritabanına kaydederken, B sitesine de durumu bildiren sayfa
// ... A sitesi kendi veritabanında güncelleme işini yaptıktan sonra B sitesine de verileri gönderiyor...
$fields = ['product_id' => '1234', 'price' => '19.90'];
$postvars = http_build_query($fields);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "https://b.site/integration.php");
curl_setopt($ch, CURLOPT_POST, count($fields));
curl_setopt($ch, CURLOPT_POSTFIELDS, $postvars);
$result = curl_exec($ch);
curl_close($ch);
// Burada da dönen $result değerine göre işlemin başarılı/başarısız oluşuna göre aksiyon alınabilir...
Dikkat: Bu örneklerde hiçbir güvenlik önlemi alınmadığı için saldırıya çok açık.
B sitesinde hangi siteden istek atıldığının tespiti, SQL injection önlemleri, A sitesinin B sitesine istek göndermeden önce B sitesinde oturum açması veya bir token alması...
Ama temel olarak sunucular arası veritabanı bağlantısı kuramıyorsanız siz de böyle bir yola başvurabilirsiniz.
Eğer her component kendi isteğinin verilerini sadece kendisi kullanacaksa istekleri component'lerin kendi içinde tutmanız iyidir.
Eğer bazı istekler birden çok component'i etkilecekse bu yönetimi ana component'te tutmak iyidir.
React, ana component'te herhangi bir state değişimi olduğunda tüm alt component'lerini tekrar kontrol eder ve DOM'da bir değişiklik gerekip gerekmediğine bakar. Eğer gerekmiyosa DOM'u güncellemez. Ama yine de bu kontrolün de bir maliyeti vardır.
Örneğin ana component'inizde 5 tane alt component var. Bu component'lerden hepsi kendi isteğini atıyor ve dönen veriyi kendi içinde işliyor. Ama biri var ki, dönen sonucu işledikten sonra bir de ana component'e veri iletmesi gerekiyor.
İşte bu durumda React ana component'te bir aksiyon gerçekleştiği için 5 component'i birden yeniden taramak zorunda kalıyor ki bu değişikliğin onları etkileyip etkilemediğinden emin olsun...
Bu durumun önüne geçmelisiniz. Kendi yağında kavrulan 4 component'inizin tekrar kontrol edilmemesini sağlamalısınız. Bunun için de bu 4 component'i React.memo()
fonksiyonu içine alabilirsiniz.
Böylelikle React bu component'leri, onlara gönderdiği parametrelerde bir değişiklik olmadığı için, yeniden kontrol etmeyecek. Onları sanki pure component gibi varsayıp geçecek.
Ben bu durumda muhtemelen 4 component'i React.memo()
korumasına alırdım ama 5.component'in isteğini o component'in içinde değil ana component'te atardım. Sonucu da props yoluyla 5.component'e iletirdim.
Ama tabi hangi yöntemi kullandığınızda daha iyi performans alacağınız sizin kurgunuza bağlı. Belki de tüm istekleri ana component'te atmalı ve sonuçları diğer component'lere prop yoluyla iletmelisinizdir...
<div id="infinite-scroll">
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</div>
#infinite-scroll { width: 400px; height:400px; padding:5px; overflow-y: scroll;}
.item { margin:5px; height:150px; background-color: #ccc; }
const $scrollView = document.getElementById("infinite-scroll");
$scrollView.addEventListener("scroll", function (e) {
const scrollTop = e.target.scrollTop;
const contentHeight = e.target.scrollHeight - e.target.offsetHeight;
if (contentHeight <= scrollTop) {
alert("son!")
}
})
web.dev sitesinden bulduğum aşağıdaki başlıklara göz atabilirsiniz.
Bazı Animasyonlar Neden Yavaş Çalışır?
Modern tarayıcılar iki CSS özelliğini ucuza canlandırabilir: transform
ve opacity
.
Başka bir animasyon yaparsanız, saniyede 60 kare (FPS) ipeksi pürüzsüzlükte bir hız elde edemezsiniz. Bu yazı, bunun neden böyle olduğunu açıklıyor.
Animasyon Performansı ve Kare Hızı
Web'de herhangi bir animasyon kullanılırken hedefin 60 FPS'lik bir kare hızı olduğu yaygın olarak kabul edilmektedir. Bu kare hızı, animasyonlarınızın düzgün görünmesini sağlayacaktır. Web'de bir frame, ekranı güncellemek ve yeniden render etmek için gereken tüm işleri yapmak için gereken süredir. Her frame 16.7ms (1000ms / 60 ≈ 16.7) içinde tamamlanmazsa, kullanıcılar gecikmeyi algılayacaktır.
Render İşlem Sırası
Bir web sayfasında bir şey görüntülemek için tarayıcının aşağıdaki sıralı adımlardan geçmesi gerekir:
- Style: Elemente uygulanan stiller hesaplanır.
- Layout: Her elemanın geometrik şekli ve konumu bulunur.
- Paint: Her elementin pikselleri katmanlara doldurulur.
- Composite: Katmanlar ekrana çizilir.
Bu 4 atım tarayıcıların rendering pipeline'ı olarak bilinir.
Zaten yüklenmiş bir sayfada bir şeyi anime ettiğinizde, bu adımların tekrar ele alınması gerekir. Bu süreç, animasyonun gerçekleşmesi için değiştirilmesi gereken adımdan başlar.
Daha önce yazdığım gibi, bu adımlar sıralıdır. Örneğin, layout'u değiştiren bir animasyon uygularsanız, paint ve birleştirme adımlarının da yeniden çalışması gerekir. Bu nedenle, düzeni değiştiren bir şeyi canlandırmak, yalnızca kompozisyonu değiştiren bir şeyi canlandırmaktan daha pahalıdır.Daha önce yazdığım gibi, bu adımlar sıralıdır. Örneğin, layout'u değiştiren bir animasyon uygularsanız, paint ve composite adımlarının da yeniden çalışması gerekir. Bu nedenle, layout'u değiştiren bir animasyon, yalnızca composite adımını değiştiren bir animasyondan daha maliyetlidir.
Layout Animasyon Özellikleri
Layout değişiklikleri, değişiklikten etkilenen tüm öğelerin geometrisinin (konum ve boyut) hesaplanmasını içerir. Bir elementi değiştirirseniz, diğer elemanların geometrisinin de yeniden hesaplanması gerekebilir. Örneğin, <html> öğesinin genişliğini değiştirirseniz, alt öğelerinden herhangi biri etkilenebilir. Öğelerin taşma ve birbirini etkileme şekli nedeniyle, ağacın daha aşağısındaki değişiklikler bazen en üste kadar yerleşim hesaplamalarına neden olabilir.
Görünür öğelerin ağacı ne kadar büyükse, layout hesaplamalarının yapılması o kadar uzun sürer.
Paint Animasyon Özellikleri
Paint, elementlerin ekranda hangi sırayla boyanacağını belirleme işlemidir. Genellikle pipeline'daki tüm görevlerin en uzun sürenidir.
Uygulamanızdaki öğelerin katmanlar halinde nasıl gruplandığına bağlı olarak, değişenlerin yanı sıra diğer öğelerin de boyanması gerekebilir.
Composite Animasyon Özellikleri
Composite (birleştirme), sayfayı katmanlara ayırma, sayfanın nasıl görünmesi gerektiğiyle ilgili bilgileri piksellere dönüştürme ve sayfayı oluşturmak için katmanları bir araya getirme (birleştirme) işlemidir.
opacity
animasyonunun maliyeti düşükler listesine dahil edilmesinin nedeni budur. Bu özellik kendi katmanında olduğu sürece, bu özellikteki değişiklikler composite (birleştirme) adımı sırasında GPU tarafından işlenebilir. Chromium tabanlı tarayıcılar ve WebKit, opacity
ve transform
animasyonu olan herhangi bir öğe için yeni bir katman oluşturur.
Katman nedir?
Tarayıcının, canlandırılacak veya geçişi yapılacak şeyleri yeni bir katmana yerleştirerek, diğer her şeyi değil, yalnızca bu öğeleri yeniden boyaması gerekir. Photoshop'un, birlikte hareket ettirilebilen bir grup öğe içeren katman kavramına aşina olabilirsiniz. Tarayıcı oluşturma katmanları bu fikre benzer.
Tarayıcı, yeni bir katmanda hangi öğelerin olması gerektiğine karar vermekte iyiyse de, birini kaçırırsa, katman oluşturmaya zorlamanın yolları vardır. Bunu, yüksek performanslı animasyonlar nasıl oluşturulur bölümünde bulabilirsiniz.
Ancak, her katman RAM'de (geçici bellekte) yer tutacağından, yeni katman oluştururken iyi düşünmek gerekir.
Sınırlı belleğe sahip cihazlarda yeni katmanlar oluşturmak, çözmeye çalıştığınızdan daha fazla performans sorununa neden olabilir. Ek olarak, her katmanın dokularının GPU'ya yüklenmesi gerekir. Bu nedenle, CPU ve GPU arasındaki bant genişliğininin de kısıtlamasına takılarak performans kaybı yaşayabilirsiniz.
Yüksek Performanslı CSS Animasyonları Nasıl Yapılır?
Bu kılavuz size yüksek performanslı CSS animasyonlarının nasıl oluşturulacağınızı anlatır.
Bu kılavuzun önerdiği tüm CSS özellikleri çok iyi tarayıcı uyumluluğuna sahiptir:
... Bu sayfanın içeriği çok uzun olduğu için şu an çevirecek zamanım yok ama basit bir dil kullanıldığı için kolayca anlayabilirsiniz.