程序員過關斬將–分佈式系統消息異常該何去何從

異步處理模型

一旦談到分佈式,微服務等這些具有很高逼格的代名詞,總能讓你在面試中脫穎而出,不是因為這些詞的英文翻譯的好,而是現代互聯網乃至企業級開發確實在分佈式,微服務等模式下取得了良好的架構效果。無論是微服務,還是之前的SOA,總是離不開異步處理模型,小到程序中IO的處理,大到系統間的消息交互,處處都有異步的身影。

談到系統之間的消息異步處理,就不能不談消息隊列(MQ),目前業界比較流行的MQ類型請自行百度腦補。但是需要提醒一下,MQ只是實現數據異步處理的一種解決方案,沒有MQ能不能實現異步處理呢?當然能,最簡單粗暴的莫過於採用數據庫方式,消息生產者直接把數據插入數據庫,消費者採用讀取數據庫的方式來獲取數據,所以MQ並不等於異步處理哦。

異步消息處理最大程度上解耦了各個系統,為每個系統獨立擴展提供了更大空間,但是異步消息處理也同時面臨着一些挑戰,比如:消息管道性能,消息管道的高可用等,其中最貼近業務層的可能非“數據異常處理”莫屬,基本上可認為這是數據處理模型的最末端,數據流向的尾部,但往往卻是業務中比較重要的部分。

如果一條異步消息作為一個分佈式事務中的一環,那還設計到消息處理結果的反饋,分佈式協調器會根據消息結果的成功與否來決定的事務的結果。

單就異步消息消費端來講,根據不同的業務場景就有以下幾種異常處理方案

直接忽略

這是所有異常數據處理方案中最粗暴,同時也是最簡單的一種:發生異常的時候,直接忽略,什麼都不做。

面對異常不採取任何措施,乍一聽這可能是個很糟糕的方案,但是在實際業務中,這可能是完全可以接受的。如果因為錯誤導致的損失很小,甚至可以忽略,但是建立一套錯誤糾正機制的成本遠遠高於忽略異常,這種場景下選擇直接忽略往往是一種更優的方案。而且當錯誤糾正機制設計到需要人工介入操作的時候,代價會更高,而且還會引入影響其他業務的可能,更為可怕的是如果錯誤糾正機制本身出現問題,那代價更是…..

舉個很簡單的栗子:像一些登錄日誌的統計操作,如果處理某個人登錄的數據出現異常,往往會選擇直接忽略。因為統計這種業務本身就帶有數據的容錯機制,100000和100001在統計需求看來沒有什麼區別。

重試

當直接忽略的方案不可行的時候,你可能需要重試的操作。如果在重試的情況下有足夠高的成功率,那重試就是合理的選擇。重試雖然可以改正間接性的錯誤,但是它對那些違反業務規則,違反數據模型的數據無能為力。

在最理想的情況下,如果重試操作是冪等性的,什麼叫冪等性能(自己去百度吧)?事情就會簡單很多,重試操作可以放心大膽的去實施。但是在重試操作經過一段時間或者一定次數之後還未成功的話,多數情況下可能需要有一定的後續策略,比如:重試10次之後如果還是失敗,則放棄。

補償

這個策略是分佈式事務中經常用到的,與其說是補償,不如說是回滾操作。特別是在程序接收到數據會有一系列的操作的情景下,補償操作類似於事務回滾的概念,讓系統回到發生這一系列操作之前的狀態。這種補償的機制非常適合於那種有“事務”需求的場景。

你的業務中有哪些“事務”的需求場景呢?歡迎在留言中體現,另外再稍微提一下,每周送架構書籍的活動仍然在進行哦,歡迎關注

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

※網頁設計公司推薦不同的風格,搶佔消費者視覺第一線

※Google地圖已可更新顯示潭子電動車充電站設置地點!!

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※別再煩惱如何寫文案,掌握八大原則!

恕我直言你可能真的不會java第6篇:Stream性能差?不要人云亦云

一、粉絲的反饋

問:stream比for循環慢5倍,用這個是為了啥?
答:互聯網是一個新聞泛濫的時代,三人成虎,以假亂真的事情時候發生。作為一個技術開發者,要自己去動手去做,不要人云亦云。

的確,這位粉絲說的這篇文章我也看過,我就不貼地址了,也沒必要給他帶流量。怎麼說呢?就是一個不懂得測試的、不入流開發工程師做的性能測試,給出了一個危言聳聽的結論。

二、所有性能測試結論都是片面的

性能測試是必要的,但針對性能測試的結果,永遠要持懷疑態度。為什麼這麼說?

  • 性能測試脫離業務場景就是片面的性能測試。你能覆蓋所有的業務場景么?
  • 性能測試脫離硬件環境就是片面的性能測試。你能覆蓋所有的硬件環境么?
  • 性能測試脫離開發人員的知識面就是片面的性能測試。你能覆蓋各種開發人員奇奇怪怪的代碼么?

所以,我從來不相信網上的任何性能測試的文章。凡是我自己的從事的業務場景,我都要在接近生產環境的機器上自己測試一遍。 所有性能測試結論都是片面的,只有你生產環境下的運行結果才是真的。

三、動手測試Stream的性能

3.1.環境

windows10 、16G內存、i7-7700HQ 2.8HZ 、64位操作系統、JDK 1.8.0_171

3.2.測試用例與測試結論

我們在上一節,已經講過:

  • 針對不同的數據結構,Stream流的執行效率是不一樣的
  • 針對不同的數據源,Stream流的執行效率也是不一樣的

所以記住筆者的話:所有性能測試結論都是片面的,你要自己動手做,相信你自己的代碼和你的環境下的測試!我的測試結果僅僅代表我自己的測試用例和測試數據結構!

3.2.1.測試用例一

測試用例:5億個int隨機數,求最小值
測試結論(測試代碼見後文):

  • 使用普通for循環,執行效率是Stream串行流的2倍。也就是說普通for循環性能更好。
  • Stream并行流計算是普通for循環執行效率的4-5倍。
  • Stream并行流計算 > 普通for循環 > Stream串行流計算

3.2.測試用例二

測試用例:長度為10的1000000隨機字符串,求最小值
測試結論(測試代碼見後文):

  • 普通for循環執行效率與Stream串行流不相上下
  • Stream并行流的執行效率遠高於普通for循環
  • Stream并行流計算 > 普通for循環 = Stream串行流計算

3.3.測試用例三

測試用例:10個用戶,每人200個訂單。按用戶統計訂單的總價。
測試結論(測試代碼見後文):

  • Stream并行流的執行效率遠高於普通for循環
  • Stream串行流的執行效率大於等於普通for循環
  • Stream并行流計算 > Stream串行流計算 >= 普通for循環

四、最終測試結論

  • 對於簡單的数字(list-Int)遍歷,普通for循環效率的確比Stream串行流執行效率高(1.5-2.5倍)。但是Stream流可以利用并行執行的方式發揮CPU的多核優勢,因此并行流計算執行效率高於for循環。
  • 對於list-Object類型的數據遍歷,普通for循環和Stream串行流比也沒有任何優勢可言,更不用提Stream并行流計算。

雖然在不同的場景、不同的數據結構、不同的硬件環境下。Stream流與for循環性能測試結果差異較大,甚至發生逆轉。但是總體上而言:

  • Stream并行流計算 >> 普通for循環 ~= Stream串行流計算 (之所以用兩個大於號,你細品)
  • 數據容量越大,Stream流的執行效率越高。
  • Stream并行流計算通常能夠比較好的利用CPU的多核優勢。CPU核心越多,Stream并行流計算效率越高。

stream比for循環慢5倍?也許吧,單核CPU、串行Stream的int類型數據遍歷?我沒試過這種場景,但是我知道這不是應用系統的核心場景。看了十幾篇測試博文,和我的測試結果。我的結論是: 在大多數的核心業務場景下及常用數據結構下,Stream的執行效率比for循環更高。 畢竟我們的業務中通常是實實在在的實體對象,沒事誰總對List<Int>類型進行遍歷?誰的生產服務器是單核?。

五、測試代碼

<dependency>
    <groupId>com.github.houbb</groupId>
    <artifactId>junitperf</artifactId>
    <version>2.0.0</version>
</dependency>

測試用例一:

import com.github.houbb.junitperf.core.annotation.JunitPerfConfig;
import com.github.houbb.junitperf.core.report.impl.HtmlReporter;
import org.junit.jupiter.api.BeforeAll;

import java.util.Arrays;
import java.util.Random;

public class StreamIntTest {

    public static int[] arr;

    @BeforeAll
    public static void init() {
        arr = new int[500000000];  //5億個隨機Int
        randomInt(arr);
    }

    @JunitPerfConfig( warmUp = 1000, reporter = {HtmlReporter.class})
    public void testIntFor() {
        minIntFor(arr);
    }

    @JunitPerfConfig( warmUp = 1000, reporter = {HtmlReporter.class})
    public void testIntParallelStream() {
        minIntParallelStream(arr);
    }

    @JunitPerfConfig( warmUp = 1000, reporter = {HtmlReporter.class})
    public void testIntStream() {
        minIntStream(arr);
    }

    private int minIntStream(int[] arr) {
        return Arrays.stream(arr).min().getAsInt();
    }

    private int minIntParallelStream(int[] arr) {
        return Arrays.stream(arr).parallel().min().getAsInt();
    }

    private int minIntFor(int[] arr) {
        int min = Integer.MAX_VALUE;
        for (int anArr : arr) {
            if (anArr < min) {
                min = anArr;
            }
        }
        return min;
    }

    private static void randomInt(int[] arr) {
        Random r = new Random();
        for (int i = 0; i < arr.length; i++) {
            arr[i] = r.nextInt();
        }
    }
}

測試用例二:

import com.github.houbb.junitperf.core.annotation.JunitPerfConfig;
import com.github.houbb.junitperf.core.report.impl.HtmlReporter;
import org.junit.jupiter.api.BeforeAll;

import java.util.ArrayList;
import java.util.Random;

public class StreamStringTest {

    public static ArrayList<String> list;

    @BeforeAll
    public static void init() {
        list = randomStringList(1000000);
    }

    @JunitPerfConfig(duration = 10000, warmUp = 1000, reporter = {HtmlReporter.class})
    public void testMinStringForLoop(){
        String minStr = null;
        boolean first = true;
        for(String str : list){
            if(first){
                first = false;
                minStr = str;
            }
            if(minStr.compareTo(str)>0){
                minStr = str;
            }
        }
    }

    @JunitPerfConfig(duration = 10000, warmUp = 1000, reporter = {HtmlReporter.class})
    public void textMinStringStream(){
        list.stream().min(String::compareTo).get();
    }

    @JunitPerfConfig(duration = 10000, warmUp = 1000, reporter = {HtmlReporter.class})
    public void testMinStringParallelStream(){
        list.stream().parallel().min(String::compareTo).get();
    }

    private static ArrayList<String> randomStringList(int listLength){
        ArrayList<String> list = new ArrayList<>(listLength);
        Random rand = new Random();
        int strLength = 10;
        StringBuilder buf = new StringBuilder(strLength);
        for(int i=0; i<listLength; i++){
            buf.delete(0, buf.length());
            for(int j=0; j<strLength; j++){
                buf.append((char)('a'+ rand.nextInt(26)));
            }
            list.add(buf.toString());
        }
        return list;
    }
}

測試用例三:

import com.github.houbb.junitperf.core.annotation.JunitPerfConfig;
import com.github.houbb.junitperf.core.report.impl.HtmlReporter;
import org.junit.jupiter.api.BeforeAll;

import java.util.*;
import java.util.stream.Collectors;

public class StreamObjectTest {

    public static List<Order> orders;

    @BeforeAll
    public static void init() {
        orders = Order.genOrders(10);
    }

    @JunitPerfConfig(duration = 10000, warmUp = 1000, reporter = {HtmlReporter.class})
    public void testSumOrderForLoop(){
        Map<String, Double> map = new HashMap<>();
        for(Order od : orders){
            String userName = od.getUserName();
            Double v; 
            if((v=map.get(userName)) != null){
                map.put(userName, v+od.getPrice());
            }else{
                map.put(userName, od.getPrice());
            }
        }

    }

    @JunitPerfConfig(duration = 10000, warmUp = 1000, reporter = {HtmlReporter.class})
    public void testSumOrderStream(){
        orders.stream().collect(
                Collectors.groupingBy(Order::getUserName, 
                        Collectors.summingDouble(Order::getPrice)));
    }

    @JunitPerfConfig(duration = 10000, warmUp = 1000, reporter = {HtmlReporter.class})
    public void testSumOrderParallelStream(){
        orders.parallelStream().collect(
                Collectors.groupingBy(Order::getUserName, 
                        Collectors.summingDouble(Order::getPrice)));
    }
}


class Order{
    private String userName;
    private double price;
    private long timestamp;
    public Order(String userName, double price, long timestamp) {
        this.userName = userName;
        this.price = price;
        this.timestamp = timestamp;
    }
    public String getUserName() {
        return userName;
    }
    public double getPrice() {
        return price;
    }
    public long getTimestamp() {
        return timestamp;
    }

    public static List<Order> genOrders(int listLength){
        ArrayList<Order> list = new ArrayList<>(listLength);
        Random rand = new Random();
        int users = listLength/200;// 200 orders per user
        users = users==0 ? listLength : users;
        ArrayList<String> userNames = new ArrayList<>(users);
        for(int i=0; i<users; i++){
            userNames.add(UUID.randomUUID().toString());
        }
        for(int i=0; i<listLength; i++){
            double price = rand.nextInt(1000);
            String userName = userNames.get(rand.nextInt(users));
            list.add(new Order(userName, price, System.nanoTime()));
        }
        return list;
    }
    @Override
    public String toString(){
        return userName + "::" + price;
    }
}

歡迎關注我的博客,裏面有很多精品合集

  • 本文轉載註明出處(必須帶連接,不能只轉文字):字母哥博客。

覺得對您有幫助的話,幫我點贊、分享!您的支持是我不竭的創作動力! 。另外,筆者最近一段時間輸出了如下的精品內容,期待您的關注。

  • 《手摸手教你學Spring Boot2.0》
  • 《Spring Security-JWT-OAuth2一本通》
  • 《實戰前後端分離RBAC權限管理系統》
  • 《實戰SpringCloud微服務從青銅到王者》
  • 《VUE深入淺出系列》

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※網頁設計公司推薦不同的風格,搶佔消費者視覺第一線

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

※南投搬家公司費用需注意的眉眉角角,別等搬了再說!

※新北清潔公司,居家、辦公、裝潢細清專業服務

※教你寫出一流的銷售文案?

蒲公英 · JELLY技術周刊 Vol.12 尤雨溪新作 Vite, 你會支持么?

「蒲公英」期刊,每周更新,我們專註於挖掘「基礎技術、工程化、跨端框架技術、圖形編程、服務端開發、桌面開發、人工智能」等多個大方向的業界熱點,並加以專業的解讀;不僅如此,我們還精選凹凸技術文章,向大家呈現團隊內的研究技術方向。

抬頭仰望,蒲公英的種子會生根發芽,如夏花絢爛;格物致知,我們登高遠眺、滄海拾遺,以求積硅步而至千里。

登高遠眺

天高地迥,覺宇宙之無窮

前端框架

Vue3 Composition API 提案

Vue3 其中一個重量級的特性就是 Composition API,它能幫助我們更好地組織代碼。本網頁是 Composition API 的草案,詳細介紹了 Composition API 的設計動機、設計細節、具體 API 用法等。文章篇幅較長,推薦找一個悠閑的周末,泡上咖啡,帶上耳機,細細品讀一番。

工具測評: React Hook Form VS Formik

使用 React 構建表單是一件痛苦的事情,官方推薦了 Formik。本文對使用 Formik 和 React Hook Form 構建表單進行了比較,得出 React Hook Form 比 Formik 更易用、更高效的結論。如果你正巧在這方面有困惑,可實踐嘗試體驗。

Quark-h5 — 從零開始的可視化編輯器

想必你一定使用微場景生成工具製作過炫酷的 h5 頁面,除了感嘆其神奇之處有沒有想過其實現方式呢?本文從零開始實現一個 H5 編輯器項目完整設計思路和主要實現步驟,並開源前後端代碼。有需要的小夥伴可以按照該教程從零實現自己的H5編輯器。

圖形編程

初探虛幻引擎5

5月底, 遊戲公司Epic揭開了虛幻5引擎神秘的面紗,此次更新包含 Nanite虛擬微多邊形 和 全新的動態全局光照Lumen 兩大核心技術,然後展示了該引擎運行在PS5上實時渲染效果,其逼真的光照和媲美電影的細節震驚了整個行業。

工程化

Vite — 入門到實戰

Vite 是 Vue 技術生態新推出的開發工具,針對 Vue 應用的無打包開發服務器,開發者無需藉助 webpack 等打包工具,即可直接在瀏覽器中預覽 Vue 項目。Vite 的原理與本技術周刊之前介紹過的 snowpack 有着異曲同工之處,Vite 本身也表示一部分靈感來自 snowpack 項目。本文從 0 開始一步一步實現了一個簡易版本的 Vite 來講解 Vite 的技術原理,讀過本文之後,再去閱讀 Vite 的項目源碼,相信會有不小的收穫。

人工智能

杜克大學出品 AI 黑科技 PULSE 算法,讓你的照片有碼變高清

近日杜克大學開源了新型超分辨率圖像算法 PULSE,可將16×16像素的低分辨率人像放大到1024×1024像素的高分辨率。

工具推介

手把手教你快速搭建專屬的 StoryBook

Storybook是一個輔助UI控件開發的工具。通過story創建獨立的控件,讓每個控件開發都有一個獨立的開發調試環境。 Storybook的運行不依賴於項目,開發人員不用擔心由於開發環境、依賴問題導致不能開發控件。Storybook支持的框架覆蓋主流的框架(React、Vue、Angular)。 由於使用React作為技術棧,本文將介紹使用react的項目如何配置Storybook環境。

滄海拾遺

滄海拾遺,積跬步以至千里

ELF – 靈活可擴展的 HTML5 構建工具

前端工程化的問題由來已久,除了尤老師正在努力的方向,還出現過很多優秀的小工具幫助我們解決各個方面的問題,ELF 就是其中一種解放我們重複勞動的構建工具之一。

用 Git 鈎子進行簡單自動部署

除了這些工具,工程化中也還是有很多小問題,可以用很多方法去解決,自動化部署就是其中之一,如果你還不懂的如何利用 Git Hook 完成自動化部署的方法,趕緊補起這一課吧,未來正在向你招手~

歡迎關注凹凸實驗室博客:aotu.io

或者關注凹凸實驗室公眾號(AOTULabs),不定時推送文章:

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

※網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

※想知道最厲害的網頁設計公司"嚨底家"!

※幫你省時又省力,新北清潔一流服務好口碑

※別再煩惱如何寫文案,掌握八大原則!

奧迪看衰純電動車市場 新款車型延後推出

 

隨著寶馬等公司逐漸擴大投入純電動車市場,奧迪並未選擇加速緊追,相反的,奧迪並不看好純電動車市場的發展。

近日歐洲媒體 Worldcarfuns 報導,奧迪公司並不想花費大量的時間和金錢來推出出色的電動車型,來與寶馬、特斯拉等品牌的電動車競爭。

根據奧迪的純電動車產品規劃,其曾計劃推出的 R8 電動版、Q6 電動版等 4 款新純電動車,量產時間都將推遲延後。對此,奧迪董事會成員兼銷售總監 Luca de Meo 表示,奧迪對純電動車的前景並不看好,因此暫時沒有生產純電動車的計劃。

 

(圖片來源:)

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※帶您來了解什麼是 USB CONNECTOR  ?

※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!

※綠能、環保無空污,成為電動車最新代名詞,目前市場使用率逐漸普及化

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※教你寫出一流的銷售文案?

澳大學生研發電動車 續航力超越 Tesla

    電動車廠特斯拉遇到了新對手,但這並不是寶馬也不是通用汽車,而是來自澳洲大學的一群學生。這些學生研發 eVe 電動車,單次充電後以每小時 100 公里的時速行駛了 500 公里,這也打破了塵封已久的電動車續航世界紀錄。此前,這項記錄為單次充電後,以 72 公里每小時速度跑滿 500 公里。   一直以來,續航能力是電動車推廣普及的最大難題,而 eVe 打破記錄外也表明,電動車可以在合理高速下行駛數百公里。eVe 由澳洲新南威爾士大學 Sunswift 團隊學生研發,到如今已是第五代版本。Sunswift 團隊早前曾以打造太陽能汽車名聲大噪,其推出的 IVy 太陽能動力車在 2011 年跑出了時速達 88 公里/小時,創造了該領域車輛的最快時速記錄。   eVe 電動車配有傳統電池,可以採用使用常規充電樁進行電力補充,其也可以通過覆蓋車身的太陽能電池板充電,車身重量為 317公斤(700磅),使用重量 59 公斤的松下電池,用常規家用插座可在 8 小時內充滿電,若接入工業用電插口,可在 5 小時內充滿。Sunswift 團隊表示,如果 eVe 停在太陽下 8 個小時,搭載的 800 瓦太陽能電池組可以提供 2 小時行駛里程,且太陽能面板還可在車輛行駛過程中收集能量。   Sunswift 團隊負責人Hayden Smith 表示,eVe 證明太陽能電動車是傳統石化燃料汽車可行性替代方案。該團隊希望以此激勵商業公司進入這一技術領域,並促使 eVe 成為澳洲首個合法上路的太陽能電動車。     (圖片來源:)

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※為什麼 USB CONNECTOR 是電子產業重要的元件?

※網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

※台北網頁設計公司全省服務真心推薦

※想知道最厲害的網頁設計公司"嚨底家"!

※新北清潔公司,居家、辦公、裝潢細清專業服務

※推薦評價好的iphone維修中心

2020 年前上路電動車要達 100 萬輛!德國推電動車優先權以達目標

德國政府已經制定了電動汽車促進法草案,新法案有望於 2015 年 2 月 1 日生效。根據法案規定,未來在德國的電動車將獲得免費專屬停車位等多種優先權。   在此之前,德國政府曾提出,到 2020 年前,德國上路的電動車數量要達 100 萬輛。但截至 2014 年初,德國的電動車數量僅為 1.2 萬輛。電動車持有數排名世界第七,在歐洲落後法國、荷蘭以及挪威等國家。    但今年以來,德國電動汽車的銷量正在快速提升,上半年純電動汽車銷量累計達 4188 輛,插電式混合動力車累計銷售 1575 輛。其中,大眾、寶馬以及 smart 三大德國品牌總計銷售 3138 輛,市場份額超過 50%。不過,要達成上述 100 萬輛的目標,還有很長的路要走。    雖然德國政府試圖快速提升純電動汽車銷量,但並未將補貼作為刺激的首要選擇,而包括美國、南韓以及日本等國家在新能源汽車推廣的過程中,都不以補貼為拉動市場的重要手段,反而從研發及稅收等方面進行扶持。

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

※網頁設計公司推薦不同的風格,搶佔消費者視覺第一線

※想知道購買電動車哪裡補助最多?台中電動車補助資訊懶人包彙整

※南投搬家公司費用,距離,噸數怎麼算?達人教你簡易估價知識!

※教你寫出一流的銷售文案?

※超省錢租車方案

電動車也推敞篷了!Tesla 敞篷電動車預計 2017 年問世

Tesla 將推全新的敞篷電動車款,這將是特斯拉公司的第四款車型,預計在 2017 年問世。   在這之前,特斯拉曾表示將發布全新 Model X 和 Model 3 ,為了提升業績表現,特斯拉將推出更多全新車款。除了將推出全新敞篷電動車外,特斯拉還計劃售價約為 3 萬 5 千美元的 Model C。   而 Tesla 全新敞篷電動車型,可能命名為 Model R,將使用電驅動技術,百公里加速時間將小於 4 秒,最高時速可達 322km/h 。   (照片來源: Shared by CC 2.0)

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

※網頁設計公司推薦不同的風格,搶佔消費者視覺第一線

※Google地圖已可更新顯示潭子電動車充電站設置地點!!

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※別再煩惱如何寫文案,掌握八大原則!

東電紀錄指出 日本輻射污染魚 放射性鍶含量再破紀錄

文:宋瑞文(媽媽監督核電廠聯盟特約撰述)

本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

※網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

※想知道最厲害的網頁設計公司"嚨底家"!

※幫你省時又省力,新北清潔一流服務好口碑

※別再煩惱如何寫文案,掌握八大原則!

Day10-微信小程序實戰-交友小程序-實現刪除好友信息與子父組件間通信

回顧:上一次已經把消息的布局以及樣式做好了

效果圖:

 

 在removeList.js文件中,messageId就是發起這個消息的用戶了

先查看一下自定義組件的生命周期

https://developers.weixin.qq.com/miniprogram/dev/framework/custom-component/lifetimes.html

 lifetimes: {
    attached: function() {
      // 在組件實例進入頁面節點樹時執行
    },
    detached: function() {
      // 在組件實例被從頁面節點樹移除時執行
    },
  }

直接就是在lifttimes裏面進行定義的(直接就是在methods的同級的下面加上即可了)

因為要對用戶的信息進行渲染,就可以看成是一個一個的對象,所以就可以在removeLIst.js中定義一個對象

然後遇到的問題就和之前是一樣的了,就是我們得到的數據太多了,沒必要全部都要,可以選擇性的要,只需要頭像和昵稱

(所以就可以在get前面來一個field)

lifetimes: {
    attached: function () {
      // 一進來就會進行它了
      db.collection('users').doc(this.data.messageId)
      .field({
        userPhoto : true,
        nickName : true
      })
      .get().then((res)=>{
        this.setData({
            userMessage : res.data
        });
      });
    }
  }

這樣的話我們在這個頁面裏面就可以得到用戶的數據了,剩下的就是直接可以在wxml中用了

<!--components/removeList/removeList.wxml-->
<movable-area class="area">
     <movable-view direction="horizontal" class="view">{{ userMessage.nickName }}</movable-view>
     <image src="{{ userMessage.userPhoto }}" />
     <view class="delete">刪除</view>
 </movable-area>

效果圖:

 

 在之後設置刪除功能之前,先設置一下就是只要點擊了消息列表中用戶的頭像之後,就可以跳轉到這個用戶的詳情頁了

可以直接 在編輯個人信息的頁面 editUserInfo.wxml中COPY代碼  

在設置這個跳轉頁面的url的時候,因為同時要給這個url傳遞參數的,所以這個時候就要用大括號括起來了

<!--components/removeList/removeList.wxml-->
<movable-area class="area">
     <movable-view direction="horizontal" class="view">{{ userMessage.nickName }}</movable-view>
     <navigator url="{{'/pages/detail/detail?userId=' + userMessage._id}}" open-type="navigate">
     <image src="{{ userMessage.userPhoto }}" />
     </navigator>
     <view class="delete">刪除</view>
 </movable-area>

即可實現,點擊頭像跳轉到個人的詳情頁面

 

二、下面就是對刪除功能進行設計

一開始的就是,點擊了之後,要給用戶一個提示信息,讓用戶可以選擇是取消還是確定的,這裏用的是一個wx.showModel這樣一個內置的方法

 

所以就要另外的給“點擊了確定”加邏輯了,就要在微信開放文檔裏面細看這個API了

https://developers.weixin.qq.com/miniprogram/dev/api/ui/interaction/wx.showModal.html

wx.showModal({
  title: '提示',
  content: '這是一個模態彈窗',
  success (res) {
    if (res.confirm) {
      console.log('用戶點擊確定')
    } else if (res.cancel) {
      console.log('用戶點擊取消')
    }
  }
})

把查到的賦值給list,然後在用數組的filter進行刪除即可了

通過fileter過濾之後,就是過濾初和我們不想要的東西,然後把這些東西再次賦值為list,然後我們把前後的list打印出來會發現:

 

 確實是過濾掉了的

 由於如果要刪掉的話,就設計了removeList這個組件和message這各頁面之間的通信了,並且是子組件像父組件,用到事件來做的

https://developers.weixin.qq.com/miniprogram/dev/framework/custom-component/events.html

<!-- 當自定義組件觸發“myevent”事件時,調用“onMyEvent”方法 -->
<component-tag-name bindmyevent="onMyEvent" />
<!-- 或者可以寫成 -->
<component-tag-name bind:myevent="onMyEvent" />

所以在message.wxml中隊子組件remove-list設置

<remove-list wx:for="{{ userMessage }}" wx:key="{{index}}" messageId="{{ item }}"
     bindmyevent="onMyEvent"/> 
    

這樣事件監聽就寫好了,但是如何在組件中觸發呢,我們回到removelist.js中

繼續查看山脈的鏈接-微信開發文檔

Component({
  properties: {},
  methods: {
    onTap: function(){
      var myEventDetail = {} // detail對象,提供給事件監聽函數
      var myEventOption = {} // 觸發事件的選項
      this.triggerEvent('myevent', myEventDetail, myEventOption)
    }
  }
})

在removelist.js中通過:

 this.triggerEvent('myevent',list) 

前面參數,要和在 message.wxml設置的 bindmyevent,後面的myevent對應上

第二個參數就是我們 過濾剩下的list

給message傳過去之後

  onMyEvent(ev){
  this.setData({
    userMessage : ev.detail
  });

通過這樣的設置出現了一個bug,就是我們刪除第一條信息的時候,直接把第二條刪掉了,第一條被留下來了

當我們查看數據庫的時候,留下來的就是第二條信息,但是在前端显示的是第一條信息留下,第二條信息沒了

要這樣修改:

onMyEvent(ev){
    this.setData({
      userMessage : []
    },()=>{
        this.setData({
          userMessage : ev.detail
        });
    });
  }
  

先賦值為空,之後再次調用removelist,再把過濾的數組進行賦值  

 

 

 也就是全部清空之後,再重新渲染的

 

 整個邏輯:

1、在數據庫中用戶的頭像和昵稱找到,然後獲取數據

 

2、點擊刪除按鈕的時候,彈出提示框,如果用戶點了缺點刪除的話,之後我們先查詢

 找到之後,把那個消息在message列表中過濾掉

 

 3、然後再重新的更新,之後就觸發子父通信,把更新之後的list傳給

 

4、父組件拿到removelist這組件的信息

 

 拿到就更新我們的列表,這樣的話列表就發送了變化了

 

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※帶您來了解什麼是 USB CONNECTOR  ?

※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!

※綠能、環保無空污,成為電動車最新代名詞,目前市場使用率逐漸普及化

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※教你寫出一流的銷售文案?

行情利好?新能源汽車充電樁或獲千億元財政補貼

中國21日有消息指出,政府單位近期可能就新能源汽車充電設施提出新的財政補貼政策,以加油站的稅費收入轉移補貼充電樁產業,總補貼規模可高達千億元。在這之前,多個部委就制定並提出《政府機關及公共機構購買新能源汽車實施方案》,為推進新能源汽車的發展和充電設施的普及做出更明確的指導和規定。   《方案》指出,充電介面與新能源汽車數量比例不低於1:1。按前面估算,新能源汽車年更新數量為8萬輛的預測,充電設施的數量也需要至少達到同樣的量級,即年均8萬個。目前全國充電樁的數量總量約僅為4萬個左右,相關政策的出臺將使得充電設備行情的發展提速。

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※為什麼 USB CONNECTOR 是電子產業重要的元件?

※網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

※台北網頁設計公司全省服務真心推薦

※想知道最厲害的網頁設計公司"嚨底家"!

※新北清潔公司,居家、辦公、裝潢細清專業服務

※推薦評價好的iphone維修中心