Skip to content
Mithril.js 2
Main Navigation KılavuzAPI

Türkçe

English
简体中文
繁體中文
Español
Français
Русский
Português – Brasil
Deutsch
日本語
한국어
Italiano
Polski
čeština
magyar

Türkçe

English
简体中文
繁體中文
Español
Français
Русский
Português – Brasil
Deutsch
日本語
한국어
Italiano
Polski
čeština
magyar

Görünüm

Sidebar Navigation

API

Çekirdek API

m(selector, attributes, children)

render(element, vnodes)

mount(root, component)

route(root, defaultRoute, routes)

request(options)

parseQueryString(string)

buildQueryString(object)

buildPathname(object)

parsePathname(string)

trust(html)

m.fragment(attrs, children)

redraw()

censor(object, extra)

İsteğe Bağlı API

stream()

Kılavuz

Bu sayfada

stream() ​

Açıklama ​

Bir Stream, elektronik tablo uygulamalarındaki hücrelere benzer şekilde, reaktif bir veri yapısıdır.

Örneğin, bir elektronik tabloda A1 = B1 + C1 ise, B1 veya C1'in değeri değiştiğinde A1'in değeri otomatik olarak değişir.

Benzer şekilde, bir akışı diğer akışlara bağlayarak birinin değerini değiştirmek otomatik olarak diğerini güncelleyebilir. Bu özellik, maliyetli hesaplamalarınız olduğunda ve bunları her yeniden çizimde çalıştırmak yerine yalnızca gerektiğinde çalıştırmak istediğinizde kullanışlıdır.

Stream'ler Mithril.js'nin temel dağıtımında yer almaz. Stream modülünü eklemek için şunu kullanın:

javascript
var Stream = require('mithril/stream');

Ortamınız bir paketleme araç zincirini desteklemiyorsa, modülü doğrudan indirebilirsiniz:

html
<script src="https://unpkg.com/mithril/stream/stream.js"></script>

Doğrudan bir <script> etiketiyle ( require yerine) yüklendiğinde, stream kütüphanesine window.m.stream üzerinden erişilebilir. Eğer window.m zaten tanımlıysa (örneğin, ana Mithril.js betiğini de kullandığınız için), stream kütüphanesi mevcut nesneye eklenecektir. Aksi takdirde, yeni bir window.m nesnesi oluşturulur. Stream'leri Mithril.js ile birlikte doğrudan <script> etiketleriyle kullanmak istiyorsanız, mithril/stream betiğinden önce Mithril.js betiğini sayfanıza eklemelisiniz. Aksi takdirde, mithril, mithril/stream tarafından tanımlanan window.m nesnesinin üzerine yazacaktır. Kütüphaneler CommonJS modülleri olarak kullanıldığında ( require(...) ile) bu bir sorun teşkil etmez.

İmza ​

Bir akış oluşturur

stream = Stream(value)

ArgümanTipGerekliAçıklama
valueanyHayırBu argüman belirtilmişse, akışın değeri bu argümana atanır.
dönerStreamBir akış döndürür

İmzalar nasıl okunur

Statik üyeler ​

Stream.combine ​

Bağlı olduğu akışlardan herhangi biri güncellendiğinde otomatik olarak güncellenen, hesaplanmış bir akış oluşturur. Bkz. akışları birleştirme

stream = Stream.combine(combiner, streams)

ArgümanTipGerekliAçıklama
combiner(Stream..., Array) -> anyEvetbirleştirici argümanına bakın
streamsArray<Stream>EvetBirleştirilecek akışların listesi
dönerStreamBir akış döndürür

İmzalar nasıl okunur

birleştirici ​

Hesaplanan akışın değerinin nasıl üretildiğini tanımlar. Bkz. akışları birleştirme

any = combiner(streams..., changed)

ArgümanTipGerekliAçıklama
streams...Streams'in splat'ıHayırstream.combine fonksiyonuna ikinci argüman olarak aktarılan akışlara karşılık gelen, sıfır veya daha fazla sayıda akışın değişken sayıda argüman olarak (splat) geçirilmiş hali.
changedArray<Stream>EvetBir güncelleme ile değişen akışların listesi
döneranyHesaplanan bir değer döndürür

İmzalar nasıl okunur

Stream.merge ​

Akış değerlerinden oluşan bir dizi değere sahip akış oluşturur

stream = Stream.merge(streams)

ArgümanTipGerekliAçıklama
streamsArray<Stream>EvetBir akış listesi
dönerStreamDeğeri bir giriş akış değerleri dizisi olan bir akış döndürür

İmzalar nasıl okunur

Stream.scan ​

Fonksiyonu, bir akümülatör ve gelen değerle birlikte akıştaki her değerde çağırarak yeni bir akış oluşturur.

Akümülatör fonksiyonunun içinde özel stream.SKIP değerini döndürerek bağımlı akışların güncellenmesini engelleyebileceğinizi unutmayın.

stream = Stream.scan(fn, accumulator, stream)

ArgümanTipGerekliAçıklama
fn(accumulator, value) -> result | SKIPEvetBir akümülatör ve değer parametresi alan ve aynı türde yeni bir akümülatör değeri döndüren bir fonksiyon
accumulatoranyEvetAkümülatör için başlangıç değeri
streamStreamEvetDeğerleri içeren akış
dönerStreamSonucu içeren yeni bir akış döndürür

İmzalar nasıl okunur

Stream.scanMerge ​

Akışlar ve scan fonksiyonlarından oluşan çiftlerin bir dizisini alır ve belirtilen fonksiyonları kullanarak bu akışları tek bir akışta birleştirir.

stream = Stream.scanMerge(pairs, accumulator)

ArgümanTipGerekliAçıklama
pairsArray<[Stream, (accumulator, value) -> value]>EvetAkış ve scan fonksiyonları demetlerinden oluşan bir dizi
accumulatoranyEvetAkümülatör için başlangıç değeri
dönerStreamSonucu içeren yeni bir akış döndürür

İmzalar nasıl okunur

Stream.lift ​

Bağlı olduğu akışlardan herhangi biri güncellendiğinde otomatik olarak güncellenen, hesaplanmış bir akış oluşturur. Bkz. akışları birleştirme. combine fonksiyonundan farklı olarak, bu fonksiyona aktarılan akışlar bir dizi yerine değişken sayıda argüman olarak verilir. Ayrıca, geri çağırma fonksiyonu akış nesneleri yerine akışların değerlerini alır ve changed parametresi bulunmaz. Bu özellikler, lift fonksiyonunu uygulamalar için genellikle combine fonksiyonundan daha kullanıcı dostu hale getirir.

stream = Stream.lift(lifter, stream1, stream2, ...)

ArgümanTipGerekliAçıklama
lifter(any...) -> anyEvetlifter argümanına bakın
streams...Streams listesiEvetKaldırılacak akışlar
dönerStreamBir akış döndürür

İmzalar nasıl okunur

lifter ​

Hesaplanan akışın değerinin nasıl üretildiğini tanımlar. Bkz. akışları birleştirme

any = lifter(streams...)

ArgümanTipGerekliAçıklama
streams...Streams'in splat'ıHayırstream.lift fonksiyonuna aktarılan akışların değerlerine karşılık gelen, sıfır veya daha fazla sayıda değerin değişken sayıda argüman olarak (splat) geçirilmiş hali.
döneranyHesaplanan bir değer döndürür

İmzalar nasıl okunur

Stream.SKIP ​

Aşağı akışların yürütülmesini atlamak için akış geri çağırmalarına döndürülebilen özel bir değer

Stream["fantasy-land/of"] ​

Bu yöntem işlevsel olarak stream ile aynı işlevselliğe sahiptir. Fantasy Land'in Uygulanabilir spesifikasyonuna uymak için vardır. Daha fazla bilgi için Fantasy Land nedir bölümüne bakın.

stream = Stream["fantasy-land/of"](value)

ArgümanTipGerekliAçıklama
valueanyHayırBu argüman belirtilmişse, akışın değeri bu argümana atanır.
dönerStreamBir akış döndürür

Örnek üyeleri ​

stream.map ​

Değeri geri çağırma fonksiyonunun sonucuna ayarlanan bağımlı bir akış oluşturur. Bu yöntem, stream["fantasy-land/map"]'in bir takma adıdır.

dependentStream = stream().map(callback)

ArgümanTipGerekliAçıklama
callbackany -> anyEvetDönüş değeri akışın değeri olan bir geri çağırma
dönerStreamBir akış döndürür

İmzalar nasıl okunur

stream.end ​

Doğru değerine ayarlandığında, bağlı olduğu akışların aboneliğini iptal eden bir akış. Bkz. sona eren durum.

endStream = stream().end

stream["fantasy-land/of"] ​

Bu yöntem işlevsel olarak stream ile aynı işlevselliğe sahiptir. Fantasy Land'in Uygulanabilir spesifikasyonuna uymak için vardır. Daha fazla bilgi için Fantasy Land nedir bölümüne bakın.

stream = stream()["fantasy-land/of"](value)

ArgümanTipGerekliAçıklama
valueanyHayırBu argüman belirtilmişse, akışın değeri bu argümana atanır.
dönerStreamBir akış döndürür

stream["fantasy-land/map"] ​

Değeri geri çağırma fonksiyonunun sonucuna ayarlanan bağımlı bir akış oluşturur. Bkz. akışları zincirleme

Bu yöntem, Fantasy Land spesifikasyonlarına uyumluluk amacıyla sağlanmıştır. Daha fazla bilgi için Fantasy Land nedir bölümüne bakın.

dependentStream = stream()["fantasy-land/map"](callback)

ArgümanTipGerekliAçıklama
callbackany -> anyEvetDönüş değeri akışın değeri olan bir geri çağırma
dönerStreamBir akış döndürür

İmzalar nasıl okunur

stream["fantasy-land/ap"] ​

Bu yöntemin adı apply anlamına gelir. Bir akış a'nın değeri olarak bir fonksiyonu varsa, başka bir akış b bunu b.ap(a)'ya argüman olarak kullanabilir. ap'yi çağırmak, fonksiyonu akış b'nin değeriyle argüman olarak çağırır ve fonksiyon çağrısının sonucu olan başka bir akış döndürür. Bu yöntem, Fantasy Land spesifikasyonlarına uyumluluk amacıyla sağlanmıştır. Daha fazla bilgi için Fantasy Land nedir bölümüne bakın.

stream = stream()["fantasy-land/ap"](apply)

ArgümanTipGerekliAçıklama
applyStreamEvetDeğeri bir fonksiyon olan bir akış
dönerStreamBir akış döndürür

Temel kullanım ​

Stream'ler, temel Mithril.js dağıtımının bir parçası değildir. Bunları bir projeye dahil etmek için modülünü çağırın:

javascript
var stream = require('mithril/stream');

Değişken olarak akışlar ​

stream() bir akış döndürür. En temel düzeyde, bir akış bir değişken veya bir değer okuma ve atama özelliği gibi çalışır: değiştirilebilen durumu tutabilir.

javascript
var username = stream('John');
console.log(username()); // "John" yazdırır

username('John Doe');
console.log(username()); // "John Doe" yazdırır

Temel fark, bir akışın bir fonksiyon olması ve bu nedenle daha yüksek dereceli fonksiyonlara dahil edilebilmesidir.

javascript
var users = stream();

// fetch API'sini kullanarak bir sunucudan kullanıcıları isteyin
fetch('/api/users')
  .then(function (response) {
    return response.json();
  })
  .then(users);

Yukarıdaki örnekte, istek tamamlandığında users akışı yanıt verileriyle doldurulur.

Çift yönlü bağlamalar ​

Stream'ler, olay dinleyicileri (event listeners) gibi geri çağırma fonksiyonları aracılığıyla da değer alabilir.

javascript
// bir akış
var user = stream('');

// akışa çift yönlü bir bağlama
m('input', {
  oninput: function (e) {
    user(e.target.value);
  },
  value: user(),
});

Yukarıdaki örnekte, kullanıcı giriş alanına yazdıkça, user akışı giriş alanının değeriyle güncellenir.

Hesaplanan özellikler ​

Stream'ler, hesaplanan özellikleri uygulamak için kullanışlıdır:

javascript
var title = stream('');
var slug = title.map(function (value) {
  return value.toLowerCase().replace(/\W/g, '-');
});

title('Hello world');
console.log(slug()); // "hello-world" yazdırır

Yukarıdaki örnekte, slug akışının değeri, slug akışına erişildiğinde değil, title akışı güncellendiğinde hesaplanır.

Elbette, birden çok akışa dayalı özellikleri hesaplamak da mümkündür:

javascript
var firstName = stream('John');
var lastName = stream('Doe');
var fullName = stream.merge([firstName, lastName]).map(function (values) {
  return values.join(' ');
});

console.log(fullName()); // "John Doe" yazdırır

firstName('Mary');

console.log(fullName()); // "Mary Doe" yazdırır

Mithril.js'deki hesaplanan özellikler atomik olarak güncellenir: birden çok akışa bağlı olan akışlar, hesaplanmış özelliğin bağımlılık ilişkisi ne kadar karmaşık olursa olsun, bir değer güncellemesi sırasında yalnızca bir kez çalıştırılır.

Akışları zincirleme ​

Stream'ler map yöntemi kullanılarak zincirlenebilir. Zincirlenmiş bir akış, bağımlı akış olarak da bilinir.

javascript
// üst akış
var value = stream(1);

// bağımlı akış
var doubled = value.map(function (value) {
  return value * 2;
});

console.log(doubled()); // 2 yazdırır

Bağımlı akışlar reaktiftir: değerleri, üst akışlarının değeri güncellendiğinde güncellenir. Bu durum, bağımlı akışın, bağlı olduğu üst akışın değeri atanmadan önce mi yoksa sonra mı oluşturulduğuna bakılmaksızın geçerlidir.

Özel stream.SKIP değerini döndürerek bağımlı akışların güncellenmesini engelleyebilirsiniz

javascript
var skipped = stream(1).map(function (value) {
  return stream.SKIP;
});

skipped.map(function () {
  // asla çalışmaz
});

Akışları birleştirme ​

Stream'ler birden fazla üst akışa bağlı olabilir. Bu tür akışlar stream.merge() fonksiyonu kullanılarak oluşturulabilir.

javascript
var a = stream('hello');
var b = stream('world');

var greeting = stream.merge([a, b]).map(function (values) {
  return values.join(' ');
});

console.log(greeting()); // "hello world" yazdırır

Veya stream.lift() yardımcı fonksiyonunu kullanabilirsiniz

javascript
var a = stream('hello');
var b = stream('world');

var greeting = stream.lift(
  function (_a, _b) {
    return _a + ' ' + _b;
  },
  a,
  b
);

console.log(greeting()); // "hello world" yazdırır

Daha karmaşık senaryolarda, reaktif hesaplamalar sırasında akış nesnelerine doğrudan erişim sağlayan stream.combine() adında daha düşük seviyeli bir fonksiyon da mevcuttur.

javascript
var a = stream(5);
var b = stream(7);

var added = stream.combine(
  function (a, b) {
    return a() + b();
  },
  [a, b]
);

console.log(added()); // 12 yazdırır

Bir akış herhangi sayıda akışa bağımlı olabilir ve atomik olarak güncellenmesi garanti edilir. Örneğin, bir A akışının B ve C olmak üzere iki bağımlı akışı varsa ve dördüncü bir D akışı hem B hem de C'ye bağımlıysa, A'nın değeri değişirse D akışı yalnızca bir kez güncellenir. Bu durum, D akışı için tanımlanan geri çağırma fonksiyonunun, B akışının yeni bir değeri almasına rağmen C akışının henüz güncellenmediği gibi tutarsız durumlarda çalıştırılmamasını sağlar. Atomiklik ayrıca aşağı akışları gereksiz yere yeniden hesaplamamanın performans avantajlarını da beraberinde getirir.

Özel stream.SKIP değerini döndürerek bağımlı akışların güncellenmesini engelleyebilirsiniz

javascript
var skipped = stream.combine(
  function (stream) {
    return stream.SKIP;
  },
  [stream(1)]
);

skipped.map(function () {
  // asla çalışmaz
});

Akış durumları ​

Belirli bir zamanda, bir akış üç durumdan birinde olabilir: beklemede, etkin ve sona erdi.

Beklemede durum ​

Beklemede olan akışlar, parametre olmadan stream() çağrılarak oluşturulabilir.

javascript
var pending = stream();

Bir akış birden fazla akışa bağımlıysa ve üst akışlarından herhangi biri beklemede durumdaysa, bağımlı akış da beklemede durumdadır ve değerini güncellemez.

javascript
var a = stream(5);
var b = stream(); // beklemede olan akış

var added = stream.combine(
  function (a, b) {
    return a() + b();
  },
  [a, b]
);

console.log(added()); // tanımsız yazdırır

Yukarıdaki örnekte, added beklemede olan bir akıştır, çünkü üst öğesi b de beklemede.

Bu, stream.map aracılığıyla oluşturulan bağımlı akışlar için de geçerlidir:

javascript
var value = stream();
var doubled = value.map(function (value) {
  return value * 2;
});

console.log(doubled()); // `doubled` beklemede olduğundan tanımsız yazdırır

Etkin durum ​

Bir akışa bir değer atandığında etkinleşir (eğer akış sonlandırılmamışsa).

javascript
var stream1 = stream('hello'); // stream1 etkin

var stream2 = stream(); // stream2 beklemede başlar
stream2('world'); // sonra etkin hale gelir

Birden çok üst öğesi olan bağımlı bir akış, tüm üst öğeleri etkinse etkin hale gelir.

javascript
var a = stream('hello');
var b = stream();

var greeting = stream.merge([a, b]).map(function (values) {
  return values.join(' ');
});

Yukarıdaki örnekte, a akışı etkindir, ancak b beklemede. b("world") ifadesi çalıştırıldığında, b akışı etkinleşir ve bu da greeting akışının da etkinleşerek değerinin "hello world" olarak güncellenmesine yol açar.

Sona eren durum ​

Bir akış, stream.end(true) çağrılarak bağımlı akışlarını etkilemeyi durdurabilir. Bu işlem, akış ile ona bağlı olan akışlar arasındaki bağlantıyı keser.

javascript
var value = stream();
var doubled = value.map(function (value) {
  return value * 2;
});

value.end(true); // sona eren duruma ayarla

value(5);

console.log(doubled());
// `doubled` artık `value`'ya bağımlı olmadığından tanımsız yazdırır

Sonlandırılmış akışlar hala durum tutma özelliğine sahiptir; yani, sonlandırıldıktan sonra bile değerlerini okuyabilir ve değiştirebilirsiniz.

javascript
var value = stream(1);
value.end(true); // sona eren duruma ayarla

console.log(value(1)); // 1 yazdırır

value(2);
console.log(value()); // 2 yazdırır

Bir akışın sınırlı bir ömrü olduğu durumlarda bir akışı sona erdirmek yararlı olabilir (örneğin, bir DOM öğesi yalnızca sürüklenirken mousemove olaylarına tepki vermek, ancak bırakıldıktan sonra değil).

Akışları serileştirme ​

Stream'ler bir .toJSON() yöntemi uygular. Bir akış JSON.stringify()'a argüman olarak iletildiğinde, akışın değeri serileştirilir.

javascript
var value = stream(123);
var serialized = JSON.stringify(value);
console.log(serialized); // 123 yazdırır

Akışlar yeniden çizimi tetiklemez ​

Knockout gibi kütüphanelerin aksine, Mithril.js akışları şablonların yeniden işlenmesini tetiklemez. Yeniden çizim, Mithril.js bileşen görünümlerinde tanımlanan olay işleyicilerine, rota değişikliklerine veya m.request çağrıları tamamlandıktan sonra yanıt olarak gerçekleşir.

Diğer eşzamansız olaylara (örneğin, setTimeout/setInterval, websocket aboneliği, 3. taraf kütüphane olay işleyicisi vb.) yanıt olarak yeniden çizim isteniyorsa, m.redraw()'ı manuel olarak çağırmalısınız.

Fantasy Land nedir ​

Fantasy Land, ortak cebirsel yapıların birlikte çalışabilirliğini belirtir. Basitçe ifade etmek gerekirse, Fantasy Land spesifikasyonlarına uygun kütüphaneler, bu yapıları nasıl uyguladıklarından bağımsız olarak çalışan, genel amaçlı fonksiyonel kod yazmak için kullanılabilir.

Örneğin, plusOne adlı genel bir fonksiyon oluşturmak istediğimizi varsayalım. Basit uygulama şöyle görünür:

javascript
function plusOne(a) {
  return a + 1;
}

Bu uygulamayla ilgili sorun, yalnızca bir sayıyla kullanılabilmesidir. Ancak, a değişkenine değer atayan mantık, bir hata durumu da üretebilir (örneğin, Sanctuary veya Ramda-Fantasy kütüphanelerinden bir Maybe veya Either yapısı içinde) veya bir Mithril.js akışı, bir Flyd akışı vb. olabilir. İdeal olarak, a'nın sahip olabileceği her olası tür için aynı fonksiyonun benzer bir sürümünü yazmak istemeyiz ve tekrar tekrar sarma/açma/hata işleme kodu yazmak istemeyiz.

Fantasy Land'in yardımcı olabileceği yer burasıdır. Bu fonksiyonu bir Fantasy Land cebiri açısından yeniden yazalım:

javascript
var fl = require('fantasy-land');

function plusOne(a) {
  return a[fl.map](function (value) {
    return value + 1;
  });
}

Şimdi bu yöntem, R.Maybe, S.Either, stream vb. gibi herhangi bir Fantasy Land uyumlu Functor ile çalışır.

Bu örnek karmaşık görünebilir, ancak karmaşıklıkta bir ödünleşimdir: basit plusOne uygulaması, basit bir sisteminiz varsa ve yalnızca sayıları artırırsanız mantıklıdır, ancak Fantasy Land uygulaması, birçok sarmalayıcı soyutlaması ve yeniden kullanılan algoritma içeren büyük bir sisteminiz varsa daha güçlü hale gelir.

Fantasy Land'i benimseyip benimsemeyeceğinize karar verirken, ekibinizin işlevsel programlama konusundaki aşinalığını göz önünde bulundurmalı ve ekibinizin kod kalitesini koruma konusunda (yeni özellikler yazma ve son teslim tarihlerini karşılama baskısına karşı) taahhüt edebileceği disiplin düzeyi konusunda gerçekçi olmalısınız. Fonksiyonel programlama yaklaşımı, çok sayıda küçük, net bir şekilde tanımlanmış fonksiyonun bir araya getirilmesine, yönetilmesine ve etkin bir şekilde kullanılmasına dayanır. Bu nedenle, yeterli dokümantasyon alışkanlığı olmayan ve/veya fonksiyonel programlama dillerinde deneyimi bulunmayan ekipler için uygun olmayabilir.

Pager
Önceki sayfacensor(object, extra)
Sonraki sayfaKılavuz

MIT Lisansı altında yayınlanmıştır.

Copyright (c) 2024 Mithril Contributors

https://mithril.js.org/stream.html

MIT Lisansı altında yayınlanmıştır.

Copyright (c) 2024 Mithril Contributors