nanadjei2's avatar

Controller won't return response after job successfully runs

I have a job in my controller which I am using to upload images. When I test with Insomnia or Postman I get my success response but when am testing with my front-end react application I don't receive any response. This is my controller method:

   public function store()
{
    request()->validate(['property_id' => 'required|integer', 'images' => 'required|array', 'image.*' => "required|mimes:jpeg,bmp,jpg,png|between:1, 6000"]);

    UploadPropertyImagesJob::dispatchNow(request()->images);

    return $this->apiRespondWithSuccess('Image Uploaded Successfully', ["data" => "someObject of data"]);
}
0 likes
22 replies
Nakov's avatar

@nanadjei2 and checking your network tab in the browser says that the request has been run? And there is no response at all? Or you just expect something to happen?

nanadjei2's avatar

@nakov Network response says: failed to load response data. Or do I need WebSocket for this?

Nakov's avatar

@nanadjei2 why would you need a WebSocket for a simple request to the backend?

Can you share the code that you use in the script please?

nanadjei2's avatar

@nakov This is my handle method in the Job;

        public function handle()
     {
    foreach ($this->imageFiles as $requestImage) {
        $requestImage->getClientOriginalName(); // Someimage.png

        $image = $requestImage->getRealPath();

        Cloudder::upload($image, null, ["folder" => $this->uploadDirectory]);

        list($width, $height) = getimagesize($image);

        $publicId = Cloudder::getPublicId();
        Cloudder::show($publicId, ["width" => $width, "height" => $height]);

        //save to uploads directory
        // $image->move(public_path("uploads"), $name);

        //Save images
        $this->saveImages($publicId, $requestImage);

        logger()->info("Image uploaded successfully");
     }
  }
Nakov's avatar

@nanadjei2 I am not talking about the code in your controller nor your job, as that's the part that does work as you say you tested it using Postman..

I am asking for your React code, did you make sure that the request has been made, with all the necessary params that are used?

This is a POST route I assume, so did you make sure that the CSRF token has been sent as well?

nanadjei2's avatar

Yes the images get uploaded successfully but for some reasons it looks like it cannot get out of my Job class.

When I return request()->all(), I get {"property_id":"42","images":[{},{}]}

Nakov's avatar

@nanadjei2 when you return request()->all() before validation it works right?

Something seems odd to me.. in the validator, you have this:

request()->validate([
    'property_id' => 'required|integer', 
    'images' => 'required|array', 
    'image.*' => "required|mimes:jpeg,bmp,jpg,png|between:1, 6000"
]);

So there are two different keys used, one is images and the other one is image, shouldn't it be: images.*?

nanadjei2's avatar

But at least I should get a validation error. And moreover, it works with postman.

Nakov's avatar

But you get failed to load response data is that a 422 response code? As I said the network tab should show you more details for the request. You should have APP_DEBUG=true in your .env file so it will give more details I believe.

nanadjei2's avatar

The problem is, after the code gets into the Job class it cannot come out again. I see the request for images in my network tab returns pending... and later returns cancelled but meanwhile, everything was successful

nanadjei2's avatar

I got it fixed by setting the timeout of axios a little longer. Thanks @nakov

Nakov's avatar

@nanadjei2 you never shown the JS code in order for me to give you better suggestion. However to me increasing a timeout is not a solution as the user is left out hanging on a blocking thread, if he/she clicks somewhere on the page the request will again fail. But you know what works for you best :)

Nakov's avatar

@nanadjei2 I asked couple of times for you to share the script that you are running, but you are not willing to do so the best solution is the one that works for you.

nanadjei2's avatar

I have a helper am using to perform all my axios request. Am sending the data with formData.

     let formData = new FormData();
        // add images to formdata
        images.forEach(image => {
          formData.append("images[]", image[0]);

      HttpRequest({
          url: "property/upload/images",
          type: "post",
          data: formData,
          user: "admin",
          application: "multipart/form-data"
        })
          .then(response => {
              toast(
                <Notify
                  body="Property has been saved successfully"
                  type="success"
                />
              );
          isLoadingState(false);
          })
          .catch(error => {
            isLoadingState(false);
          });
nanadjei2's avatar

That is in the axios configuration.

     const axiosInstance = Axios.create({
     timeout: 180000,
    headers: {
      Authorization: `Bearer ${localStorage["jwt"] ? localStorage["jwt"] : ""}`,
      "Content-Type": application
    }
   });
Nakov's avatar

@nanadjei2 wow, 3 minutes timeout. What happens if you try to upload many images and then you click somewhere else or close the browser?

nanadjei2's avatar

Please, you are not proposing any solution or approach by which I can get the issue solved.

Nakov's avatar

@nanadjei2 you are using Job and yet you are dispatching it immediately hence the reason the request takes so very long. You should setup a queue system instead which will schedule the job and run it in the background without blocking the main thread and the user to do whatever else he/she wants to do.

https://laravel.com/docs/master/queues#dispatching-jobs

so don't use dispatchNow as that's a blocker, but use dispatch. So read the documentation for Queues:

https://laravel.com/docs/master/queues#running-the-queue-worker

Watch some videos on using Queues here on Laracasts. That's my solution.

Ap3twe's avatar

If is working accept an answer so we know

Please or to participate in this conversation.