Создайте ленту фотографий с помощью Go и Vue.js

Вам потребуются установленные на вашем компьютере Go и SQLite, а также базовые знания Go и JavaScript.

Многие приложения для социальных сетей позволяют пользователям загружать фотографии, и эти фотографии обычно отображаются на временной шкале для просмотра их подписчиками и другими людьми. Раньше вам приходилось обновлять ленту вручную, чтобы увидеть новые фотографии, загруженные на временную шкалу. Однако современные веб-технологии позволяют просматривать обновления в режиме реального времени без необходимости обновлять страницу вручную.

В этой статье мы рассмотрим, как можно создать ленту фотографий в реальном времени, используя Pusher Channels, GO и немного Vue.js. Каналы толкателя помогает вам «легко создавать масштабируемые уведомления в приложении, чат, графики в реальном времени, геотрекинг и многое другое в ваших веб-приложениях и мобильных приложениях с помощью нашего размещенного API обмена сообщениями pub/sub».

Это предварительный просмотр того, что мы будем строить:

Предпосылки

Прежде чем мы начнем создавать наше приложение, убедитесь, что у вас есть:

Давайте начнем.

Получение приложения Pusher Channels

Первым шагом будет получение приложения Pusher Channels. Нам потребуются учетные данные приложения, чтобы наши функции реального времени работали.

Перейдите на сайт Pusher и создайте учетную запись. После создания учетной записи следует создать новое приложение. Следуйте указаниям мастера создания приложения, после чего вам должны быть предоставлены учетные данные приложения, которые мы будем использовать позже в этой статье.

Теперь, когда у нас есть наше приложение, давайте перейдем к следующему шагу.

Создание нашего приложения Go

Следующее, что мы хотим сделать, это создать приложение Go. В вашем терминале cd на ваш $GOPATH и создайте там новый каталог.

    $ cd $GOPATH/src
    $ mkdir gofoto
    $ cd gofoto

💡 Рекомендуется размещать исходный код вашего проекта в src подкаталог (например, $GOPATH/src/your_project или же $GOPATH/src/github.com/your_github_username/your_project.

Далее мы создадим несколько каталогов, чтобы немного упорядочить наше приложение:

    $ mkdir database
    $ mkdir public
    $ mkdir public/uploads

Это создаст database а также public справочник, а также uploads каталог внутри общедоступного каталога. Мы будем хранить наш файл базы данных внутри database каталог, мы будем хранить наши общедоступные файлы: HTML и изображения, внутри public а также uploads каталог. Создать новый index.html файл в public каталог, который был создан.

Теперь давайте создадим наш первый (и единственный) файл Go для этой статьи. Мы постараемся все упростить, поместив весь наш исходный код в один файл. Создать main.go файл в корне проекта.

В файле вставьте следующее:

    <span class="hljs-keyword">package</span> main

    <span class="hljs-keyword">import</span> (
        <span class="hljs-string">"database/sql"</span>
        <span class="hljs-string">"io"</span>
        <span class="hljs-string">"net/http"</span>
        <span class="hljs-string">"os"</span>

        <span class="hljs-string">"github.com/labstack/echo"</span>
        <span class="hljs-string">"github.com/labstack/echo/middleware"</span>
        _ <span class="hljs-string">"github.com/mattn/go-sqlite3"</span>
        pusher <span class="hljs-string">"github.com/pusher/pusher-http-go"</span>
    )

Выше мы импортировали некоторые пакеты, которые нам понадобятся для работы с нашим фотопотоком. Нам нужно database/sql для выполнения SQL-запросов, io а также os пакет для нашего процесса загрузки файлов, и net/http для наших кодов состояния HTTP.

У нас есть некоторые другие внешние пакеты, которые мы импортировали. labstack/echo пакет это Эхо-фреймворк что мы будем использовать. У нас также есть mattn/go-sqlite3 пакет для SQLite. Наконец, мы импортировали pusher/pusher-http-go package, который мы будем использовать для запуска событий в Pusher Channels.

Импорт внешних пакетов Go

Прежде чем мы продолжим, давайте загрузим эти пакеты с помощью нашего терминала. Выполните следующие команды ниже, чтобы загрузить пакеты:

    $ go get github.com/labstack/echo
    $ go get github.com/labstack/echo/middleware
    $ go get github.com/mattn/go-sqlite3
    $ go get github.com/pusher/pusher-http-go

Обратите внимание, что приведенные выше команды не возвращают никакого подтверждения после завершения установки пакетов. Если вы хотите убедиться, что пакеты действительно были установлены, вы можете просто проверить $GOPATH/src/github.com каталог.

Теперь, когда мы загрузили наши пакеты, давайте создадим main функция. Это функция, которая будет точкой входа нашего приложения. В этой функции мы настроим базу данных приложений, промежуточное ПО и маршруты.

Открой main,go файл и вставьте следующий код:

    <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
        db := initialiseDatabase(<span class="hljs-string">"database/database.sqlite"</span>)
        migrateDatabase(db)

        e := echo.New()

        e.Use(middleware.Logger())
        e.Use(middleware.Recover())

        e.File(<span class="hljs-string">"/"</span>, <span class="hljs-string">"public/index.html"</span>)
        e.GET(<span class="hljs-string">"/photos"</span>, getPhotos(db))
        e.POST(<span class="hljs-string">"/photos"</span>, uploadPhoto(db))
        e.Static(<span class="hljs-string">"/uploads"</span>, <span class="hljs-string">"public/uploads"</span>)

        e.Logger.Fatal(e.Start(<span class="hljs-string">":9000"</span>))
    }

В приведенном выше коде мы создали экземпляр нашей базы данных, используя путь к файлу базы данных. Это создаст файл SQLite, если он еще не существует. Затем мы запускаем migrateDatabase функция, которая мигрирует базу данных.

Затем мы создаем экземпляр Echo, а затем регистрируем некоторые промежуточные программы. промежуточное ПО регистратора полезен для регистрации информации о HTTP-запросе, когда восстановить промежуточное ПО «восстанавливается после паники в любом месте цепочки, печатает трассировку стека и передает управление централизованному HTTPErrorHandler».

Затем мы настраиваем некоторые маршруты для обработки наших запросов. Первым обработчиком является File обработчик. Мы используем это для обслуживания index.html файл. Это будет точка входа в приложение из внешнего интерфейса. У нас также есть /photos маршрут, который принимает POST а также GET запрос. Нам нужно, чтобы эти маршруты действовали как конечные точки API, которые используются для загрузки и отображения фотографий. Конечный обработчик Static. Мы используем это для возврата статических файлов, которые хранятся в /uploads каталог.

Мы, наконец, используем e.Start чтобы запустить наш веб-сервер Go, работающий на порту 9000. Порт не установлен в камне, и вы можете выбрать любой доступный и неиспользуемый порт, который вам нравится.

На данный момент мы еще не создали большинство функций, на которые ссылались в main функция, поэтому давайте сделаем это сейчас.

Создание наших функций управления базой данных

в main функция, на которую мы ссылались initialiseDatabase а также migrateDatabase функция. Давайте создадим их сейчас. в main.go файл, вставьте следующие функции над main функция:

    <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">initialiseDatabase</span><span class="hljs-params">(filepath <span class="hljs-keyword">string</span>)</span> *<span class="hljs-title">sql</span>.<span class="hljs-title">DB</span></span> {
        db, err := sql.Open(<span class="hljs-string">"sqlite3"</span>, filepath)
        <span class="hljs-keyword">if</span> err != <span class="hljs-literal">nil</span> || db == <span class="hljs-literal">nil</span> {
            <span class="hljs-built_in">panic</span>(<span class="hljs-string">"Error connecting to database"</span>)
        }

        <span class="hljs-keyword">return</span> db
    }

    <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">migrateDatabase</span><span class="hljs-params">(db *sql.DB)</span></span> {
        sql := <span class="hljs-string">`
            CREATE TABLE IF NOT EXISTS photos(
                    id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
                    src VARCHAR NOT NULL
            );
       `</span>

        _, err := db.Exec(sql)
        <span class="hljs-keyword">if</span> err != <span class="hljs-literal">nil</span> {
            <span class="hljs-built_in">panic</span>(err)
        }
    }

в initialiseDatabase мы создаем экземпляр базы данных SQLite, используя файл базы данных, и возвращаем этот экземпляр. в migrateDatabase мы используем экземпляр базы данных, возвращенный в предыдущей функции, для выполнения миграции SQL.

Давайте создадим структуру данных для нашей фотографии и фотоколлекции.

Создание наших структур данных

Следующее, что мы сделаем, это создадим структуру данных для наших типов объектов. Мы создадим Photo структура и PhotoCollection структура. Photo структура будет определять, как будет представлена ​​типичная фотография, в то время как PhotoCollection будет определять, как будет представлена ​​коллекция фотографий.

Открой main.go файл и вставьте следующий код над initialiseDatabase функция:

    <span class="hljs-keyword">type</span> Photo <span class="hljs-keyword">struct</span> {
        ID  <span class="hljs-keyword">int64</span>  <span class="hljs-string">`json:"id"`</span>
        Src <span class="hljs-keyword">string</span> <span class="hljs-string">`json:"src"`</span>
    }

    <span class="hljs-keyword">type</span> PhotoCollection <span class="hljs-keyword">struct</span> {
        Photos []Photo <span class="hljs-string">`json:"items"`</span>
    }

Создание наших функций обработчика маршрута

Далее давайте создадим функции для наших маршрутов. Открой main.go файл и вставьте в него следующий файл:

    <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">getPhotos</span><span class="hljs-params">(db *sql.DB)</span> <span class="hljs-title">echo</span>.<span class="hljs-title">HandlerFunc</span></span> {
        <span class="hljs-keyword">return</span> <span class="hljs-function"><span class="hljs-keyword">func</span><span class="hljs-params">(c echo.Context)</span> <span class="hljs-title">error</span></span> {
            rows, err := db.Query(<span class="hljs-string">"SELECT * FROM photos"</span>)
            <span class="hljs-keyword">if</span> err != <span class="hljs-literal">nil</span> {
                <span class="hljs-built_in">panic</span>(err)
            }

            <span class="hljs-keyword">defer</span> rows.Close()

            result := PhotoCollection{}

            <span class="hljs-keyword">for</span> rows.Next() {
                photo := Photo{}

                err2 := rows.Scan(&photo.ID, &photo.Src)
                <span class="hljs-keyword">if</span> err2 != <span class="hljs-literal">nil</span> {
                    <span class="hljs-built_in">panic</span>(err2)
                }

                result.Photos = <span class="hljs-built_in">append</span>(result.Photos, photo)
            }

            <span class="hljs-keyword">return</span> c.JSON(http.StatusOK, result)
        }
    }

    <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">uploadPhoto</span><span class="hljs-params">(db *sql.DB)</span> <span class="hljs-title">echo</span>.<span class="hljs-title">HandlerFunc</span></span> {
        <span class="hljs-keyword">return</span> <span class="hljs-function"><span class="hljs-keyword">func</span><span class="hljs-params">(c echo.Context)</span> <span class="hljs-title">error</span></span> {
            file, err := c.FormFile(<span class="hljs-string">"file"</span>)
            <span class="hljs-keyword">if</span> err != <span class="hljs-literal">nil</span> {
                <span class="hljs-keyword">return</span> err
            }

            src, err := file.Open()
            <span class="hljs-keyword">if</span> err != <span class="hljs-literal">nil</span> {
                <span class="hljs-keyword">return</span> err
            }

            <span class="hljs-keyword">defer</span> src.Close()

            filePath := <span class="hljs-string">"./public/uploads/"</span> + file.Filename
            fileSrc := <span class="hljs-string">" + file.Filename

            dst, err := os.Create(filePath)
            <span class="hljs-keyword">if</span> err != <span class="hljs-literal">nil</span> {
                <span class="hljs-built_in">panic</span>(err)
            }

            <span class="hljs-keyword">defer</span> dst.Close()

            <span class="hljs-keyword">if</span> _, err = io.Copy(dst, src); err != <span class="hljs-literal">nil</span> {
                <span class="hljs-built_in">panic</span>(err)
            }

            stmt, err := db.Prepare(<span class="hljs-string">"INSERT INTO photos (src) VALUES(?)"</span>)
            <span class="hljs-keyword">if</span> err != <span class="hljs-literal">nil</span> {
                <span class="hljs-built_in">panic</span>(err)
            }

            <span class="hljs-keyword">defer</span> stmt.Close()

            result, err := stmt.Exec(fileSrc)
            <span class="hljs-keyword">if</span> err != <span class="hljs-literal">nil</span> {
                <span class="hljs-built_in">panic</span>(err)
            }

            insertedId, err := result.LastInsertId()
            <span class="hljs-keyword">if</span> err != <span class="hljs-literal">nil</span> {
                <span class="hljs-built_in">panic</span>(err)
            }

            photo := Photo{
                Src: fileSrc,
                ID:  insertedId,
            }

            <span class="hljs-keyword">return</span> c.JSON(http.StatusOK, photo)
        }
    }

в getPhotos мы просто запускаем запрос, чтобы получить все фотографии из базы данных и вернуть их клиенту в виде ответа JSON. в uploadPhoto методом мы сначала получаем файл для загрузки, затем загружаем его на сервер, а затем запускаем запрос, чтобы вставить новую запись в photos таблица с только что загруженной фотографией. Мы также возвращаем ответ JSON от этой функции.

Добавление поддержки реального времени в наше приложение Go

Следующее, что мы хотим сделать, это инициировать событие, когда новая фотография загружается на сервер. Для этого мы будем использовать HTTP-библиотека Pusher Go.

в main.go файл вставьте следующее выше определения типа для Photo а также PhotoCollection:

    <span class="hljs-keyword">var</span> client = pusher.Client{
        AppId:   <span class="hljs-string">"PUSHER_APP_ID"</span>,
        Key:     <span class="hljs-string">"PUSHER_APP_KEY"</span>,
        Secret:  <span class="hljs-string">"PUSHER_APP_SECRET"</span>,
        Cluster: <span class="hljs-string">"PUSHER_APP_CLUSTER"</span>,
        Secure:  <span class="hljs-literal">true</span>,
    }

Это создаст новый экземпляр клиента Pusher. Затем мы можем использовать этот экземпляр для запуска уведомлений на разные каналы, которые нам нужны. Не забудьте заменить PUSHER_APP_* keys с ключами, предоставленными при создании приложения Pusher ранее.

Далее перейдите в uploadPhoto функция в main.go файл и прямо перед return в нижней части функции вставьте следующий код:

client.Trigger(<span class="hljs-string">"photo-stream"</span>, <span class="hljs-string">"new-photo"</span>, photo)Это код, который запускает новое событие при загрузке новой фотографии в наше приложение.

Это будет все для нашего приложения Go. На этом этапе вы можете создать свое приложение и скомпилировать его в двоичный файл, используя go build команда. Однако для этого урока мы просто временно запустим двоичный файл:

    $ go run main.go

Создание нашего интерфейса

Следующее, что мы хотим сделать, это построить наш интерфейс. Мы будем использовать Фреймворк Vue.js и Библиотека Аксиос отправлять запросы.

Открой index.html файл и вставьте туда следующий код:

    <span class="hljs-meta"><!doctype html></span>
    <span class="hljs-tag"><<span class="hljs-name">html</span> <span class="hljs-attr">lang</span>=<span class="hljs-string">"en"</span>></span>
    <span class="hljs-tag"><<span class="hljs-name">head</span>></span>
        <span class="hljs-tag"><<span class="hljs-name">meta</span> <span class="hljs-attr">charset</span>=<span class="hljs-string">"utf-8"</span>></span>
        <span class="hljs-tag"><<span class="hljs-name">meta</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"viewport"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">"width=device-width, initial-scale=1, shrink-to-fit=no"</span>></span>
        <span class="hljs-tag"><<span class="hljs-name">link</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"stylesheet"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"
        <span class="hljs-tag"><<span class="hljs-name">title</span>></span>Photo Feed<span class="hljs-tag"></<span class="hljs-name">title</span>></span>
        <span class="hljs-tag"><<span class="hljs-name">style</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text/css"</span>></span><span class="css">
            <span class="hljs-selector-id">#photoFile</span> { <span class="hljs-attribute">display</span>: none; }
            <span class="hljs-selector-id">#app</span> <span class="hljs-selector-tag">img</span> { <span class="hljs-attribute">max-width</span>: <span class="hljs-number">100%</span>; }
            <span class="hljs-selector-class">.image-row</span> { <span class="hljs-attribute">margin</span>: <span class="hljs-number">20px</span> <span class="hljs-number">0</span>; }
            <span class="hljs-selector-class">.image-row</span> <span class="hljs-selector-class">.thumbnail</span> { <span class="hljs-attribute">padding</span>: <span class="hljs-number">2px</span>; <span class="hljs-attribute">border</span>: <span class="hljs-number">1px</span> solid <span class="hljs-number">#d9d9d9</span>; }
        </span><span class="hljs-tag"></<span class="hljs-name">style</span>></span>
    <span class="hljs-tag"></<span class="hljs-name">head</span>></span>
    <span class="hljs-tag"><<span class="hljs-name">body</span>></span>
        <span class="hljs-tag"><<span class="hljs-name">div</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"app"</span>></span>

            <span class="hljs-tag"><<span class="hljs-name">nav</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"navbar navbar-expand-lg navbar-light bg-light"</span>></span>
                <span class="hljs-tag"><<span class="hljs-name">a</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"navbar-brand"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"#"</span>></span>GoFoto<span class="hljs-tag"></<span class="hljs-name">a</span>></span>
                <span class="hljs-tag"><<span class="hljs-name">div</span>></span>
                    <span class="hljs-tag"><<span class="hljs-name">ul</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"navbar-nav mr-auto"</span>></span>
                        <span class="hljs-tag"><<span class="hljs-name">li</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"nav-item active"</span>></span>
                            <span class="hljs-tag"><<span class="hljs-name">a</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"nav-link"</span> <span class="hljs-attr">v-on:click</span>=<span class="hljs-string">"filePicker"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"#"</span>></span>Upload<span class="hljs-tag"></<span class="hljs-name">a</span>></span>
                            <span class="hljs-tag"><<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"file"</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"photoFile"</span> <span class="hljs-attr">ref</span>=<span class="hljs-string">"myFiles"</span> @<span class="hljs-attr">change</span>=<span class="hljs-string">"upload"</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"file"</span> /></span>
                        <span class="hljs-tag"></<span class="hljs-name">li</span>></span>
                    <span class="hljs-tag"></<span class="hljs-name">ul</span>></span>
                <span class="hljs-tag"></<span class="hljs-name">div</span>></span>
            <span class="hljs-tag"></<span class="hljs-name">nav</span>></span>

            <span class="hljs-tag"><<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"container"</span>></span>
                <span class="hljs-tag"><<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"row justify-content-md-center"</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"loading"</span> <span class="hljs-attr">v-if</span>=<span class="hljs-string">"loading"</span>></span>
                    <span class="hljs-tag"><<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"col-xs-12"</span>></span>
                        Loading photos...
                    <span class="hljs-tag"></<span class="hljs-name">div</span>></span>
                <span class="hljs-tag"></<span class="hljs-name">div</span>></span>
                <span class="hljs-tag"><<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"row justify-content-md-center image-row"</span> <span class="hljs-attr">v-for</span>=<span class="hljs-string">"photo in photos"</span>></span>
                    <span class="hljs-tag"><<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"col col-lg-4 col-md-6 col-xs-12"</span>></span>
                        <span class="hljs-tag"><<span class="hljs-name">img</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"thumbnail"</span> <span class="hljs-attr">:src</span>=<span class="hljs-string">"photo.src"</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">""</span> /></span>
                    <span class="hljs-tag"></<span class="hljs-name">div</span>></span>
                <span class="hljs-tag"></<span class="hljs-name">div</span>></span>
            <span class="hljs-tag"></<span class="hljs-name">div</span>></span>

        <span class="hljs-tag"></<span class="hljs-name">div</span>></span>
        <span class="hljs-tag"><<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"//js.pusher.com/4.0/pusher.min.js"</span>></span><span class="undefined"></span><span class="hljs-tag"></<span class="hljs-name">script</span>></span>
        <span class="hljs-tag"><<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">" class="undefined"></span><span class="hljs-tag"></<span class="hljs-name">script</span>></span>
        <span class="hljs-tag"><<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">" class="undefined"></span><span class="hljs-tag"></<span class="hljs-name">script</span>></span>
    <span class="hljs-tag"></<span class="hljs-name">body</span>></span>
    <span class="hljs-tag"></<span class="hljs-name">html</span>></span>

В HTML-файле выше мы определили дизайн для нашего фотопотока. Мы используем Bootstrap 4 и включили CSS в HTML выше. Мы также используем библиотеку Axios, библиотеку Pusher и платформу Vue. Мы добавили ссылки на скрипты внизу HTML-документа.

Далее добавим код Vue.js. В файле HTML добавьте следующий код прямо перед закрытием body ярлык:

    <script type=<span class="hljs-string">"text/javascript"</span>>
        <span class="hljs-keyword">new</span> Vue({
            <span class="hljs-attr">el</span>: <span class="hljs-string">'#app'</span>,
            <span class="hljs-attr">data</span>: {
                <span class="hljs-attr">photos</span>: [],
                <span class="hljs-attr">loading</span>: <span class="hljs-literal">true</span>,
            },
            mounted() {
                <span class="hljs-keyword">const</span> pusher = <span class="hljs-keyword">new</span> Pusher(<span class="hljs-string">'PUSHER_APP_KEY'</span>, {
                    <span class="hljs-attr">cluster</span>: <span class="hljs-string">'PUSHER_APP_CLUSTER'</span>,
                    <span class="hljs-attr">encrypted</span>: <span class="hljs-literal">true</span>
                });

                <span class="hljs-keyword">let</span> channel = pusher.subscribe(<span class="hljs-string">'photo-stream'</span>)

                channel.bind(<span class="hljs-string">'new-photo'</span>, data => <span class="hljs-keyword">this</span>.photos.unshift(data));

                axios.get(<span class="hljs-string">'/photos'</span>).then(<span class="hljs-function"><span class="hljs-params">res</span> =></span> {
                    <span class="hljs-keyword">this</span>.loading = <span class="hljs-literal">false</span>
                    <span class="hljs-keyword">this</span>.photos = res.data.items ? res.data.items : []
                })
            },
            <span class="hljs-attr">methods</span>: {
                <span class="hljs-attr">filePicker</span>: <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
                    <span class="hljs-keyword">let</span> elem = <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">'photoFile'</span>);

                    <span class="hljs-keyword">if</span> (elem && <span class="hljs-built_in">document</span>.createEvent) {
                        <span class="hljs-keyword">let</span> evt = <span class="hljs-built_in">document</span>.createEvent(<span class="hljs-string">"MouseEvents"</span>);
                        evt.initEvent(<span class="hljs-string">"click"</span>, <span class="hljs-literal">true</span>, <span class="hljs-literal">false</span>);
                        elem.dispatchEvent(evt);
                    }
                },
                <span class="hljs-attr">upload</span>: <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
                    <span class="hljs-keyword">let</span> data = <span class="hljs-keyword">new</span> FormData();
                    data.append(<span class="hljs-string">'file'</span>, <span class="hljs-keyword">this</span>.$refs.myFiles.files[<span class="hljs-number">0</span>]);

                    axios.post(<span class="hljs-string">'/photos'</span>, data).then(<span class="hljs-function"><span class="hljs-params">res</span> =></span> <span class="hljs-built_in">console</span>.log(res))
                }
            }
        });
    <span class="xml"><span class="hljs-tag"></<span class="hljs-name">script</span>></span></span>

Выше мы создали экземпляр Vue и сохранили свойства photos а также loading. photos Свойство хранит список фотографий и loading просто содержит логическое значение, указывающее, загружаются фотографии или нет.

в mounted мы создаем экземпляр нашей библиотеки Pusher. Затем мы слушаем на photo-stream канал для new-photo мероприятие. Когда событие срабатывает, мы добавляем новую фотографию из события в photos список. Мы также отправляем запрос GET на /photos чтобы получить все фотографии из API. Заменить PUSHER_APP_* ключи с одним из панели управления Pusher.

в methods свойство, мы добавили несколько методов. filePicker запускается при нажатии кнопки «Загрузить» в пользовательском интерфейсе. Он запускает средство выбора файлов, которое позволяет пользователю загружать фотографии. upload Метод принимает загруженный файл и отправляет запрос POST с файлом в API для обработки.

Это все, что касается внешнего интерфейса, вы можете сохранить файл и перейти к своему веб-браузеру. Посещать чтобы увидеть ваше приложение в действии.

Вот как это будет выглядеть снова:

Вывод

В этой статье мы смогли продемонстрировать, как вы можете использовать Pusher Channels в своем приложении Go, чтобы предоставить вашему приложению функции в реальном времени. Как видно из приведенных выше примеров кода, начать работу с Pusher Channels очень просто. Проверить документация чтобы увидеть другие способы использования Pusher Channels для предоставления пользователям функций в реальном времени.

Исходный код этого приложения доступен на Гитхаб.

Этот пост впервые появился на Блог пушера.

Похожие записи

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *