简体   繁体   中英

create Vue function to update textarea without buffering

So I have a laravel app that gets data from a server and displays it in a textarea. I want that textarea to update incrementally (without buffering) as the data comes back from the server. Right now it waits till all the data is received and then updates the text area. More details:

There's a vue function that updates a text area in a laravel app. It does it on this line in the below large section:

axios.post('/' + task + '/' + websiteid, this.$data).then(function (response) {                
return _this3.comment_body += '|------  ' + task + ' output  ---->\n' + response.data;

.

new Vue({
    el: '#app',

    data: {
        comment_body: '', 
        updated: false,
        errors: new Errors(),
        commandoutput: new CommandOutput(),
        pending_response: false,
        prefix: 'example',
        updating: false
    },
    mounted: function mounted() {
        window.onbeforeunload = this.leaving;
        // window.onblur = this.leaving;
        // window.onmouseout = this.leaving;
    },

    methods: {
        onSubmitUpdate: function onSubmitUpdate(websiteid) {
            var _this = this;

            // eventually hook this thing up
            this.$data.loading = true;
            this.$data.updating = true;
            axios.post('/websites/' + websiteid + '/updates', this.$data).then(function (response) {
                return location.reload(); 
            }).catch(function (error) {
                return _this.errors.record(error.response.data.errors);
            });
        },
        saveProgress: function saveProgress(websiteid) {
            var _this2 = this;

            axios.post('/websites/' + websiteid + '/save', this.$data).then(function (response) {
                return location.reload();
            }).catch(function (error) {
                return _this2.errors.record(error.response.data.errors);
            });
        },
        onCommand: function onCommand(task, websiteid) {
            var _this3 = this;

            axios.post('/' + task + '/' + websiteid, this.$data).then(function (response) {                
                return _this3.comment_body += '|------  ' + task + ' output  ---->\n' + response.data;
            }).catch(function (error) {
                return _this3.errors.record(error.response.data.errors);
            });
        },
        leaving: function leaving() {
            if (document.getElementById("update-comment").value.trim() !== "" && this.$data.updated == false) {
                return true;
            }
        }
    }
});

This is the text area it updates:

<textarea name="comment_body" id="update-comment" placeholder="output goes here, feel free to notate" rows="10" class="update-comment"></textarea>

Here is the php code that gets data from the server

var_dump( "something1");
echo "$command";
$this->process_wrapper($command);
echo "something4";


public function process_wrapper($cmd, $data = null)
{
    $descr = array(
        0 => array(
            'pipe',
            'r'
        ) ,
        1 => array(
            'pipe',
            'w'
        ) ,
        2 => array(
            'pipe',
            'w'
        )
    );
    $pipes = array();
    echo "something2";
    //ob_flush();
    flush();
    echo "something3";
    $process = proc_open($cmd, $descr, $pipes,realpath('./'),array());
    if (is_resource($process)) {
        while ($f = fgets($pipes[1])) {
            echo $f;
            //ob_flush();
            flush();
        }
    }
}

Whenever I uncomment one of those two ob_flush() calls it gives me an error and says I have no buffer. This is good, I don't want any buffer, I want everything to display as soon as it is echoed or produced.

However, Vue waits until everything is done and then displays everything at once (whether in the var_dump or echo statements or the data from the server) How would I display everything from PHP as it runs without buffering? I have already tested my apache buffering with this script https://www.jeffgeerling.com/blog/2016/streaming-php-disabling-output-buffering-php-apache-nginx-and-varnish and that is not the issue here. I haven't used Vue before. Thanks.

EDIT: Since the echo statements in php are not displaying till later I think there is some sort of buffer somewhere that is catching all the output from the echo statements and waiting to display them untill "onCommand" method in Vue is run. I found this in another part of the application but I'm not sure if this anything to do with it:

/**
 * Runs when a command is due to be sent.
 *
 * @param Swift_Transport_SmtpAgent $agent            to read/write
 * @param string                    $command          to send
 * @param int[]                     $codes            expected in response
 * @param string[]                  $failedRecipients to collect failures
 * @param bool                      $stop             to be set true  by-reference if the command is now sent
 */
public function onCommand(Swift_Transport_SmtpAgent $agent, $command, $codes = array(), &$failedRecipients = null, &$stop = false);

EDIT: this might be relevant:

/**
 * Run a command against the buffer, expecting the given response codes.
 *
 * If no response codes are given, the response will not be validated.
 * If codes are given, an exception will be thrown on an invalid response.
 *
 * @param string   $command
 * @param int[]    $codes
 * @param string[] $failures An array of failures by-reference
 *
 * @return string
 */
public function executeCommand($command, $codes = array(), &$failures = null)
{
    $failures = (array) $failures;
    $stopSignal = false;
    $response = null;
    foreach ($this->getActiveHandlers() as $handler) {
        $response = $handler->onCommand(
            $this, $command, $codes, $failures, $stopSignal
            );
        if ($stopSignal) {
            return $response;
        }
    }

    return parent::executeCommand($command, $codes, $failures);
}

(actually this doesn't seem to be run at all)

EDIT: A co-worker actually fixed this using socket.io using a redis adapter to display the data will post the fix once I have time.

I don't quite understand what you're trying to do, and I haven't read your PHP file but you should bind the comment_body data to your input (textarea), Vue makes this possible with the use of v-model - much like Angular. <textarea v-model="comment_body"></textarea>

Also, data must be a function. So instead of

data: {
 comment_body: ''
}

it must be

data() {
 return {
  comment_body: ''
 }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM