Inhaltsverzeichnis
Vorwort
Eine Lesezeichenanwendung
DienstServerseitige Aggregation" >DienstServerseitige Aggregation
Clientseitige Aggregation
更进一步
Heim Web-Frontend js-Tutorial Eine kurze Diskussion zum JavaScript-Tutorial zur funktionalen Programmierung (Bild)

Eine kurze Diskussion zum JavaScript-Tutorial zur funktionalen Programmierung (Bild)

Mar 13, 2017 pm 05:12 PM

Vorwort

Als ich Anfang April in Peking war, sagte Klassenkamerad Xu Hao, dass die von Kollegen in unserem Unternehmen geschriebenen Artikel zu einfach seien und zu viel Wert auf Details legten. Dann nahm ich die Sesamkörner und die Wassermelone verloren, also habe ich den Blog nicht erneut aktualisiert (eigentlich liegt die Ursache darin, dass das Projekt zu beschäftigt ist). Letzte Woche habe ich mit mehreren anderen Kollegen an der Veranstaltung „Martin Fowler Shenzhen Tour“ teilgenommen. Mein Kollege Tashi und ich haben zusammen mit Yang Yun (in Jianghu als „Big Devil“ bekannt) eine „FullStack Language JavaScript“ beigesteuert ) )s Thema ist „Beherrschung der funktionalen Programmierung und Steuerung der Systemkomplexität“, und das Thema von Li Xin (in Jianghu als Xin Ye bekannt) ist „Parallelität: Vergangenheit und Leben nach dem Tod“.

Während ich mit anderen Kollegen probte, stellte ich plötzlich fest, dass unsere Themen mehr oder weniger zusammenhingen. Der Teil, über den ich gesprochen habe, betraf auch ereignisbasierte Parallelitätsmechanismen und funktionale Programmierung. Wenn Sie sorgfältig darüber nachdenken, sollte es mit den Eigenschaften von JavaScript selbst zusammenhängen:

  1. Event-Based Node.js ist ein sehr typisches Modell für Parallelität

  2. Funktionale Programmierung sorgt dafür, dass Rückrufe auf natürliche Weise unterstützt werden, wodurch es sich sehr gut für asynchrone/Ereignismechanismen eignet.

  3. Funktionale Programmierfunktionen machen es sehr gut zum Schreiben geeignet DSL

Am Tag nach dem Treffen wollte ich plötzlich ein Aggregationsmodell mithilfe funktionaler Programmierung im Projektcode neu schreiben. Es stellte sich heraus, dass die Idee vage verwandt war zu NoSQL und stellte außerdem fest, dass ich viele Mängel hatte.

Das folgende Beispiel stammt aus einer Szene in einem tatsächlichen Projekt, aber die Domäne wurde geändert, was jedoch keinerlei Auswirkungen auf das Lesen und Verstehen des Mechanismus dahinter hat.

Eine Lesezeichenanwendung

Stellen Sie sich eine Anwendung vor, in der Benutzer eine Liste der abonnierten RSS sehen können. Jedes Element in der Liste (Feed genannt) enthält ein id, einen Artikeltitel title und einen Link zum Artikel url.

Das Datenmodell sieht so aus:

var feeds = [
    {
        'id': 1,
        'url': 'http://abruzzi.github.com/2015/03/list-comprehension-in-python/',
        'title': 'Python中的 list comprehension 以及 generator'
    },
    {
        'id': 2,
        'url': 'http://abruzzi.github.com/2015/03/build-monitor-script-based-on-inotify/',
        'title': '使用inotify/fswatch构建自动监控脚本'
    },
    {
        'id': 3,
        'url': 'http://abruzzi.github.com/2015/02/build-sample-application-by-using-underscore-and-jquery/',
        'title': '使用underscore.js构建前端应用'
    }
];
Nach dem Login kopieren

Das Modell ist sehr einfach, wenn diese einfache Anwendung keine benutzerbezogenen Informationen hat. Doch bald musste die Anwendung von der Standalone-Version auf die Webversion erweitert werden, das heißt, wir führten das Konzept der Benutzer ein. Jeder Benutzer kann eine solche Liste sehen. Darüber hinaus können Benutzer auch Feeds sammeln. Natürlich können Benutzer nach dem Sammeln auch die Liste der gesammelten Feeds einsehen.

feed and user

Da jeder Benutzer mehrere Feeds sammeln kann und jeder Feed auch von mehreren Benutzern gesammelt werden kann, ist die Viele-zu-Viele-Beziehung zwischen ihnen wie in der Abbildung oben dargestellt . Sie denken vielleicht auch an Dinge wie:

$ curl http://www.php.cn/:9999/user/1/feeds
Nach dem Login kopieren

, um alle 1 Benutzer feed usw. abzurufen, aber diese sind nicht wichtig. Das eigentliche Problem besteht darin, dass, nachdem Sie alle Feeds erhalten haben, In der Benutzeroberfläche oben müssen Sie jedem Feed ein -Attribut makred hinzufügen. Dieses Attribut wird verwendet, um anzugeben, ob der Feed erfasst wurde. Entsprechend der Schnittstelle kann es sich um einen gelben Stern oder ein rotes Herz handeln.

bookmarkds design

DienstServerseitige Aggregation

Aufgrund der Einschränkungen relationaler Datenbanken müssen Sie eine Aggregation auf der Serverseite durchführen B. Feeding. Wickeln Sie das -Objekt ein, um ein Objekt wie FeedWrapper zu generieren:

public class FeedWrapper {
    private Feed feed;
    private boolean marked;

    public boolean isMarked() {
        return marked;
    }

    public void setMarked(boolean marked) {
        this.marked = marked;
    }

    public FeedWrapper(Feed feed, boolean marked) {
        this.feed = feed;
        this.marked = marked;
    }
}
Nach dem Login kopieren

und definieren Sie dann ein Dienstobjekt wie FeedService:

public ArrayList<FeedWrapper> wrapFeed(List<Feed> markedFeeds, List<Feed> feeds) {
    return newArrayList(transform(feeds, new Function<Feed, FeedWrapper>() {
        @Override
        public FeedWrapper apply(Feed feed) {
            if (markedFeeds.contains(feed)) {
                return new FeedWrapper(feed, true);
            } else {
                return new FeedWrapper(feed, false);
            }
        }
    }));
}
Nach dem Login kopieren

Okay, dies kann als passable Implementierung betrachtet werden, aber statischesstark typisiertes Java ist etwas zurückhaltend, dies zu tun, und sobald neue Änderungen auftreten (was mit ziemlicher Sicherheit passieren wird), müssen wir diesen Teil noch einfügen die Logik Fügen Sie es in JavaScript ein und sehen Sie, wie es diesen Prozess vereinfacht.

Clientseitige Aggregation

Kommen wir zum Thema. In diesem Artikel verwenden wir lodash als funktionale Programmierbibliothek, um das Schreiben von Code zu vereinfachen. Da es sich bei JavaScript um eine dynamisch schwach typisierte Sprache handelt, können wir einem Objekt jederzeit Attribute hinzufügen. Auf diese Weise kann eine einfache map-Operation den obigen Java-Code vervollständigen:

_.map(feeds, function(item) {
    return _.extend(item, {marked: isMarked(item.id)});
});
Nach dem Login kopieren

wobei die Funktion isMarked wird so etwas tun:

var userMarkedIds = [1, 2];
function isMarked(id) {
    return _.includes(userMarkedIds, id);
}
Nach dem Login kopieren

Das heißt, es wird überprüft, ob die eingehenden Parameter in einer Liste enthalten sind userMarkedIds Diese Liste kann durch die folgende Anfrage abgerufen werden:

$ curl http://www.php.cn/:9999/user/1/marked-feed-ids
Nach dem Login kopieren

Der Zweck, nur die ID zu erhalten, besteht darin, die Datengröße der Netzwerkübertragung zu reduzieren. Natürlich können Sie auch alle /marked-feeds anfordern und dann _.pluck(feeds, &#39;id&#39;) lokal ausführen, um alle id-Attribute zu extrahieren.

嗯,代码是精简了许多。但是如果仅仅能做到这一步的话,也没有多大的好处嘛。现在需求又有了变化,我们需要在另一个页面上展示当前用户的收藏夹(用以展示用户所有收藏的feed)。作为程序员,我们可不愿意重新写一套界面,如果能复用同一套逻辑当然最好了。

比如对于上面这个列表,我们已经有了对应的模板:

{{#each feeds}}
<li class="list-item">
    <p class="section" data-feed-id="{{this.id}}">
        {{#if this.marked}}
            <span class="marked icon-favorite"></span>
        {{else}}
            <span class="unmarked icon-favorite"></span>
        {{/if}}
        <a href="/feeds/{{this.url}}">
            <p class="detail">
                <h3>{{this.title}}</h3>
            </p>
        </a>
    </p>
</li>
{{/each}}
Nach dem Login kopieren

事实上,这段代码在收藏夹页面上完全可以复用,我们只需要把所有的marked属性都设置为true就行了!简单,很快我们就可以写出对应的代码:

_.map(feeds, function(item) {
    return _.extend(item, {marked: true});
});
Nach dem Login kopieren

漂亮!而且重要的是,它还可以如正常工作!但是作为程序员,你很快就发现了两处代码的相似性:

_.map(feeds, function(item) {
    return _.extend(item, {marked: isMarked(item.id)});
});

_.map(feeds, function(item) {
    return _.extend(item, {marked: true});
});
Nach dem Login kopieren

消除重复是一个有追求的程序员的基本素养,不过要消除这两处貌似有点困难:位于marked:后边的,一个是函数调用,另一个是值!如果要简化,我们不得不做一个匿名函数,然后以回调的方式来简化:

function wrapFeeds(feeds, predicate) {
    return _.map(feeds, function(item) {
        return _.extend(item, {marked: predicate(item.id)});
    });
}
Nach dem Login kopieren

对于feed列表,我们要调用:

wrapFeeds(feeds, isMarked);
Nach dem Login kopieren

而对于收藏夹,则需要传入一个匿名函数:

wrapFeeds(feeds, function(item) {return true});
Nach dem Login kopieren

lodash中,这样的匿名函数可以用_.wrap来简化:

wrapFeeds(feeds, _.wrap(true));
Nach dem Login kopieren

好了,目前来看,简化的还不错,代码缩减了,而且也好读了一些(当然前提是你已经熟悉了函数式编程的读法)。

更进一步

如果仔细审视isMarked函数,会发现它对外部的依赖不是很漂亮(而且这个外部依赖是从网络异步请求来的),也就是说,我们需要在请求到markedIds的地方才能定义isMarked函数,这样就把函数定义绑定到了一个固定的地方,如果该函数的逻辑比较复杂,那么势必会影响代码的可维护性(或者更糟糕的是,多出维护)。

要将这部分代码隔离出去,我们需要将ids作为参数传递出去,并得到一个可以当做谓词(判断一个id是否在列表中的谓词)的函数。

简而言之,我们需要:

var predicate = createFunc(ids);
wrapFeeds(feeds, predicate);
Nach dem Login kopieren

这里的createFunc函数接受一个列表作为参数,并返回了一个谓词函数。而这个谓词函数就是上边说的isMarked。这个神奇的过程被称为柯里化currying,或者偏函数partial。在lodash中,这个很容易实现:

function isMarkedIn(ids) {
    return _.partial(_.includes, ids);
}
Nach dem Login kopieren

这个函数会将ids保存起来,当被调用时,它会被展开为:_.includes(ids, <id>)。只不过这个<id>会在实际迭代的时候才传入:

$(&#39;/marked-feed-ids&#39;).done(function(ids) {
    var wrappedFeeds = wrapFeeds(feeds, isMarkedIn(ids));
    console.log(wrappedFeeds);
});
Nach dem Login kopieren

这样我们的代码就被简化成了:

$(&#39;/marked-feed-ids&#39;).done(function(ids) {
    var wrappedFeeds = wrapFeeds(feeds, isMarkedIn(ids));
    var markedFeeds = wrapFeeds(feeds, _.wrap(true));

    allFeedList.html(template({feeds: wrappedFeeds}));
    markedFeedList.html(template({feeds: markedFeeds}));
});
Nach dem Login kopieren













Das obige ist der detaillierte Inhalt vonEine kurze Diskussion zum JavaScript-Tutorial zur funktionalen Programmierung (Bild). Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn

Heiße KI -Werkzeuge

Undresser.AI Undress

Undresser.AI Undress

KI-gestützte App zum Erstellen realistischer Aktfotos

AI Clothes Remover

AI Clothes Remover

Online-KI-Tool zum Entfernen von Kleidung aus Fotos.

Undress AI Tool

Undress AI Tool

Ausziehbilder kostenlos

Clothoff.io

Clothoff.io

KI-Kleiderentferner

Video Face Swap

Video Face Swap

Tauschen Sie Gesichter in jedem Video mühelos mit unserem völlig kostenlosen KI-Gesichtstausch-Tool aus!

Heiße Werkzeuge

Notepad++7.3.1

Notepad++7.3.1

Einfach zu bedienender und kostenloser Code-Editor

SublimeText3 chinesische Version

SublimeText3 chinesische Version

Chinesische Version, sehr einfach zu bedienen

Senden Sie Studio 13.0.1

Senden Sie Studio 13.0.1

Leistungsstarke integrierte PHP-Entwicklungsumgebung

Dreamweaver CS6

Dreamweaver CS6

Visuelle Webentwicklungstools

SublimeText3 Mac-Version

SublimeText3 Mac-Version

Codebearbeitungssoftware auf Gottesniveau (SublimeText3)

Einfaches JavaScript-Tutorial: So erhalten Sie den HTTP-Statuscode Einfaches JavaScript-Tutorial: So erhalten Sie den HTTP-Statuscode Jan 05, 2024 pm 06:08 PM

JavaScript-Tutorial: So erhalten Sie HTTP-Statuscode. Es sind spezifische Codebeispiele erforderlich. Vorwort: Bei der Webentwicklung ist häufig die Dateninteraktion mit dem Server erforderlich. Bei der Kommunikation mit dem Server müssen wir häufig den zurückgegebenen HTTP-Statuscode abrufen, um festzustellen, ob der Vorgang erfolgreich ist, und die entsprechende Verarbeitung basierend auf verschiedenen Statuscodes durchführen. In diesem Artikel erfahren Sie, wie Sie mit JavaScript HTTP-Statuscodes abrufen und einige praktische Codebeispiele bereitstellen. Verwenden von XMLHttpRequest

So erhalten Sie auf einfache Weise HTTP-Statuscode in JavaScript So erhalten Sie auf einfache Weise HTTP-Statuscode in JavaScript Jan 05, 2024 pm 01:37 PM

Einführung in die Methode zum Abrufen des HTTP-Statuscodes in JavaScript: Bei der Front-End-Entwicklung müssen wir uns häufig mit der Interaktion mit der Back-End-Schnittstelle befassen, und der HTTP-Statuscode ist ein sehr wichtiger Teil davon. Das Verstehen und Abrufen von HTTP-Statuscodes hilft uns, die von der Schnittstelle zurückgegebenen Daten besser zu verarbeiten. In diesem Artikel wird erläutert, wie Sie mithilfe von JavaScript HTTP-Statuscodes erhalten, und es werden spezifische Codebeispiele bereitgestellt. 1. Was ist ein HTTP-Statuscode? HTTP-Statuscode bedeutet, dass der Dienst den Dienst anfordert, wenn er eine Anfrage an den Server initiiert

Welche Vorteile bietet die Verwendung von C++-Lambda-Ausdrücken für die funktionale Programmierung? Welche Vorteile bietet die Verwendung von C++-Lambda-Ausdrücken für die funktionale Programmierung? Apr 17, 2024 am 10:18 AM

C++-Lambda-Ausdrücke bringen Vorteile für die funktionale Programmierung, darunter: Einfachheit: Anonyme Inline-Funktionen verbessern die Lesbarkeit des Codes. Wiederverwendung von Code: Lambda-Ausdrücke können übergeben oder gespeichert werden, um die Wiederverwendung von Code zu erleichtern. Kapselung: Bietet eine Möglichkeit, einen Codeabschnitt zu kapseln, ohne eine separate Funktion zu erstellen. Praktischer Fall: Filterung ungerader Zahlen in der Liste. Berechnen Sie die Summe der Elemente in einer Liste. Lambda-Ausdrücke erreichen die Einfachheit, Wiederverwendbarkeit und Kapselung funktionaler Programmierung.

Wie kann man Golang-Funktionsprogramme mithilfe einer verzögerten Auswertung optimieren? Wie kann man Golang-Funktionsprogramme mithilfe einer verzögerten Auswertung optimieren? Apr 16, 2024 am 09:33 AM

Die verzögerte Auswertung kann in Go mithilfe von verzögerten Datenstrukturen implementiert werden: Erstellen eines Wrapper-Typs, der den tatsächlichen Wert kapselt und ihn nur bei Bedarf auswertet. Optimieren Sie die Berechnung von Fibonacci-Folgen in Funktionsprogrammen, indem Sie die Berechnung von Zwischenwerten aufschieben, bis sie tatsächlich benötigt werden. Dadurch kann unnötiger Overhead vermieden und die Leistung funktionaler Programme verbessert werden.

Häufige Fehler und Fallstricke der Golang-Funktionsprogrammierung Häufige Fehler und Fallstricke der Golang-Funktionsprogrammierung Apr 30, 2024 pm 12:36 PM

Bei der Verwendung funktionaler Programmierung in Go sind fünf häufige Fehler und Fallstricke zu beachten: Vermeiden Sie versehentliche Änderungen von Referenzen und stellen Sie sicher, dass neu erstellte Variablen zurückgegeben werden. Um Parallelitätsprobleme zu lösen, verwenden Sie Synchronisierungsmechanismen oder vermeiden Sie die Erfassung externer veränderlicher Zustände. Gehen Sie mit Teilfunktionalisierung sparsam um, um die Lesbarkeit und Wartbarkeit des Codes zu verbessern. Behandeln Sie Fehler in Funktionen immer, um die Robustheit Ihrer Anwendung sicherzustellen. Berücksichtigen Sie die Auswirkungen auf die Leistung und optimieren Sie Ihren Code mithilfe von Inline-Funktionen, abgeflachten Datenstrukturen und Stapelverarbeitung von Vorgängen.

Python-Lambda-Ausdrücke: abgekürzt, prägnant, kraftvoll Python-Lambda-Ausdrücke: abgekürzt, prägnant, kraftvoll Feb 19, 2024 pm 08:10 PM

PythonLambda-Ausdrücke sind ein leistungsstarkes und flexibles Tool zum Erstellen prägnanter, lesbarer und benutzerfreundlicher Codes. Sie eignen sich hervorragend zum schnellen Erstellen anonymer Funktionen, die als Argumente an andere Funktionen übergeben oder in Variablen gespeichert werden können. Die grundlegende Syntax eines Lambda-Ausdrucks lautet wie folgt: lambdaarguments:expression Der folgende Lambda-Ausdruck fügt beispielsweise zwei Zahlen hinzu: lambdax,y:x+y Dieser Lambda-Ausdruck kann wie folgt als Argument an eine andere Funktion übergeben werden: defsum( x ,y):returnx+yresult=sum(lambdax,y:x+y,1,2)In diesem Beispiel

Python-Lambda-Ausdrücke: Entdecken Sie die Leistungsfähigkeit anonymer Funktionen Python-Lambda-Ausdrücke: Entdecken Sie die Leistungsfähigkeit anonymer Funktionen Feb 24, 2024 am 09:01 AM

Der Lambda-Ausdruck in Python ist eine weitere Syntaxform einer anonymen Funktion. Es handelt sich um eine kleine anonyme Funktion, die an einer beliebigen Stelle im Programm definiert werden kann. Ein Lambda-Ausdruck besteht aus einer Parameterliste und einem Ausdruck, der jeder gültige Python-Ausdruck sein kann. Die Syntax eines Lambda-Ausdrucks lautet wie folgt: lambdaargument_list:expression. Der folgende Lambda-Ausdruck gibt beispielsweise die Summe zweier Zahlen zurück: lambdax,y:x+y. Dieser Lambda-Ausdruck kann an andere Funktionen wie die Karte übergeben werden () Funktion: Zahlen=[ 1,2,3,4,5]Ergebnis=Karte(Lambda

Welche Vor- und Nachteile haben Java-Funktionen im Vergleich zu anderen funktionalen Programmiersprachen? Welche Vor- und Nachteile haben Java-Funktionen im Vergleich zu anderen funktionalen Programmiersprachen? Apr 24, 2024 pm 02:51 PM

Zu den Vorteilen der funktionalen Java-Programmierung gehören Einfachheit, Zusammensetzbarkeit, Parallelität, Testfreundlichkeit und Leistung. Zu den Nachteilen gehören Lernkurve, Schwierigkeiten beim Debuggen, begrenzte Flexibilität und Leistungsaufwand. Zu seinen Hauptmerkmalen gehören reine Funktionen ohne Nebenwirkungen, Datenverarbeitungspipelines, zustandsloser Code und effiziente Streaming-APIs.

See all articles