Isomorphic flux เรนเดอร์บนเซิร์ฟเวอร์หลังจากการร้องขอทั้งหมด

ฉันมีปัญหาในการหาวิธีที่ดีที่สุดในการให้บริการเพื่อแสดงส่วนประกอบการตอบสนองของฉันหลังจากที่คำขอ http ได้รับการแก้ไขแล้วเท่านั้น

ตัวอย่างเช่น:

ส่วนประกอบ A ‹- ส่วนประกอบ B ‹- ส่วนประกอบ C (C ทริกเกอร์การดำเนินการซึ่งทำการเรียกไปยัง API และส่งคืนข้อมูลเพื่อแสดงผล ในขณะเดียวกันก็เพียงแสดงผล 'กำลังโหลด')

เมื่อตรวจสอบซอร์สโค้ดของฉัน ฉันเห็นเพียง 'กำลังโหลด' และต้องการให้เซิร์ฟเวอร์รอจนกว่าการเรียกของคอมโพเนนต์ C ได้รับการแก้ไขและแสดงผลเพื่อจุดประสงค์ SEO

ตามทฤษฎีแล้ว มันฟังดูง่ายเพราะเซิร์ฟเวอร์ควรเรียกใช้การกระทำนั้นเอง และรอจนกว่าการดำเนินการจะเสร็จสิ้น จากนั้นจึงโทร react.renderToString() เช่นนี้:

server.get('/', function (req, res, next) {
    showMessages({}, function showMessagesCallback() { //add a callback
        var html = React.renderToString(ChatComponent());
        res.send(html);
    });
});

แต่จะเกิดอะไรขึ้นหากองค์ประกอบหลายรายการทำการเรียกการดำเนินการ และฉันต้องรอหลายการดำเนินการเพื่อแก้ไข จากนั้นจึงเรียก renderToString

แต่คำขอจะถูกรับจากฝั่งไคลเอ็นต์แทน ไฟล์เซิร์ฟเวอร์ของฉัน:

/**
 * This leverages Express to create and run the http server.
 * A Fluxible context is created and executes the navigateAction
 * based on the URL. Once completed, the store state is dehydrated
 * and the application is rendered via React.
 */

import express from 'express';
import path from 'path';
import serialize from 'serialize-javascript';
import {navigateAction} from 'fluxible-router';
import debugLib from 'debug';
import React from 'react';
import app from './app';
import HtmlComponent from 'components/Html';
const htmlComponent = React.createFactory(HtmlComponent);

const debug = debugLib('quran-com');

const server = express();
server.set('state namespace', 'App');
server.use('/public', express.static(path.join(__dirname, '/build')));
server.use('/images', express.static(path.join(__dirname, '/client/images')));
server.use('/fonts', express.static(path.join(__dirname, '/client/styles/fonts')));

server.use((req, res, next) => {
    let context = app.createContext();

    debug('Executing navigate action');
    context.getActionContext().executeAction(navigateAction, {
        url: req.url
    }, (err) => {
        if (err) {
            if (err.status && err.status === 404) {
                next();
            } else {
                next(err);
            }
            return;
        }

        debug('Exposing context state');
        const exposed = 'window.App=' + serialize(app.dehydrate(context)) + ';';

        debug('Rendering Application component into html');
        const html = React.renderToStaticMarkup(htmlComponent({
            context: context.getComponentContext(),
            state: exposed,
            markup: React.renderToString(context.createElement())
        }));

        debug('Sending markup');
        res.type('html');
        res.write('<!DOCTYPE html>' + html);
        res.end();
    });
});

const port = process.env.PORT || 8000;
server.listen(port);
console.log('Listening on port ' + port);

export default server;

วิธีที่ดีที่สุดในการทำเช่นนี้คืออะไร?


person Mohamed El Mahallawy    schedule 17.05.2015    source แหล่งที่มา
comment
ฉันไม่เข้าใจว่าคุณกำลังพยายามแก้ไขปัญหาอะไร ข้อมูลใดที่ควรแสดงผล? มันเอามาจากไหน?   -  person WiredPrairie    schedule 17.05.2015
comment
อะไรจะแสดงผลฝั่งเซิร์ฟเวอร์เฉพาะเมื่อคำขอ http ทั้งหมดส่งคืนแล้ว หมายถึง? คำขอ HTTP ชุดนี้ที่คุณอ้างถึงคืออะไร และคุณหมายถึงอะไรกับการส่งคืน? คุณมีตัวอย่างที่เป็นรูปธรรมหรือไม่?   -  person August Lilleaas    schedule 17.05.2015
comment
@WiredPrairie ฉันอัปเดตคำถามเพื่ออธิบายได้ดีขึ้น   -  person Mohamed El Mahallawy    schedule 17.05.2015
comment
คุณจะต้องใช้เทคนิคเพื่อชะลอการเรนเดอร์ขั้นสุดท้ายจนกว่าคอมโพเนนต์ทั้งหมดจะดึงข้อมูลหรือรวมศูนย์คำขอข้อมูล แล้วรออีกครั้ง   -  person WiredPrairie    schedule 18.05.2015
comment
@WiredPrairie โอเคฟังดูดี - ทำอย่างไร? :)   -  person Mohamed El Mahallawy    schedule 18.05.2015
comment
ฉันคิดว่าคำตอบที่ดีสำหรับ StackOverflow ที่ยาวเกินไป   -  person WiredPrairie    schedule 18.05.2015


คำตอบ (1)


คุณต้องคิดใหม่เกี่ยวกับสถาปัตยกรรมของแอปของคุณ ส่วนประกอบต่างๆ ไม่ควรรับข้อมูลด้วยตนเอง คุณจะดีกว่าเมื่อมีบางสิ่งให้ข้อมูลแก่ส่วนประกอบเหล่านั้น

คำแนะนำของฉันคือให้ทำในการดำเนินการนำทาง เพื่อให้กลายเป็นจุดเริ่มต้นในมุมมองใดๆ จากนั้นที่นี่ คุณสามารถแก้ไขข้อมูลทั้งหมดที่จำเป็นและฟีดจัดเก็บด้วยข้อมูลนั้น เมื่อแก้ไขแล้วให้โทรกลับ เช่น.:

module.exports = {

    navigateAction: function (context, state, done) {
        var completeNavigation = function () {
            context.dispatch('NAVIGATE_DONE');
            done()
        }

        var route = _.last(state.routes);

        debug('navigate to: ' + route.name);

        switch (route.name) {
            case 'products':
                context.executeAction(productActions.loadProducts, null, completeNavigation);
                break;
            default:
                completeNavigation();
                break;
        }

    }

};

ในตัวอย่างนี้ฉันใช้ react-router

person Tomas Kirda    schedule 17.05.2015
comment
ฉันอยู่กับคุณที่ร้านค้าโดยเก็บข้อมูลและพุชไปยังส่วนประกอบต่างๆ +1 ในเรื่องนั้น ฉันชอบแนวทางของคุณในการดำเนินการบางอย่างตามที่เซิร์ฟเวอร์เรียก เป็นขั้นตอนแรกที่รอให้ทุกอย่างแก้ไข ฉันไม่สามารถเพียง .waitFor จากร้านค้าทั้งหมดได้หรือไม่ - person Mohamed El Mahallawy; 18.05.2015