0

I am looking for a way with a Form API form in Drupal to have an #ajax event on a form field. When submitted, this calls a remote API.

How can I stream the response out to the screen without the request being terminated before completing the stream read?

I thought maybe I could do this in the #ajax callback:

  /**
   * {@inheritdoc}
   */
  public function getResponse(array &$form, FormStateInterface $form_state) {
    $prompt = $form_state->getValue('prompt');
    $model = $form_state->getValue('model');

    $stream = $this->client->completions()->createStreamed(
      [
        'model' => $model,
        'prompt' => trim($prompt),
      ],
    );

    foreach ($stream as $response) {
      $value = $form['response']['#value'];
      $value .= ' ' . trim($response->choices[0]->text) ?? $this->t('No answer was provided.');
      $form['response']['#value'] = $value;
      return $form['response'];
    }
  }

But this won't work. Is there a way to do this within Drupal currently?

7
  • Could you clarify what "won't work" means exactly? Is the response content unexpected? Error messages/codes? Is your server stack set up to flush buffers correctly per the Symfony docs? Where are you flushing the response? (your sample code is missing context to know where it's run, it will never go past the first iteration)
    – Clive
    May 10 at 16:08
  • If you're more asking if there's a Drupal-specific pattern/wrapper for this, I think the answer is probably "not yet"
    – Clive
    May 10 at 16:23
  • Updated question. Haven't really streamed anything before, so not sure what is missing.
    – Kevin
    May 10 at 16:23
  • Is that the actual code? Including the foreach loop? That will never work, because a function can only return once. It'll never get past the first iteration of the loop. I'm not even sure there's really a use case for this - the AJAX response will be JSON, and valid JSON needs the whole document to be parsed. The receiver would have to wait until all parts of the response were streamed before it could make sense of the output
    – Clive
    May 10 at 16:27
  • Ok, so it really cannot be done (from a form?). I have tried a handful of ways using StreamedResponse and other examples. Even if called from JS it would hit an internal route to validate user access. I was trying to stream large responses to the client so it didn't take dozens of seconds to see the response.
    – Kevin
    May 10 at 16:30

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Browse other questions tagged or ask your own question.