Laravel Dusk - выполнить скрипт javascript и дождаться разрешения обещания вернуть значение - PullRequest
0 голосов
/ 18 апреля 2019

Я хочу запустить скрипт, который будет ожидать обещания, возвращающего значение.

$dusk->script('return //something');

Функция JavaScript, которую я хочу запустить, является обещанием.

fetch(url).then(r => r.blob()).then(blob => {
    var reader = new FileReader();
    reader.onload = function() {
        var b64 = reader.result.replace(/^data:.+;base64,/, '');
        console.log(b64); // I want to return this value
    };
    reader.readAsDataURL(blob);
});

Iхотите вернуть переменную b64, но этого не произойдет.

$b64 = $dusk->script("
    var b64;

    fetch(url).then(r => r.blob()).then(blob => {
        var reader = new FileReader();
        reader.onload = function() {
            b64 = reader.result.replace(/^data:.+;base64,/, ''); 
        };
        reader.readAsDataURL(blob);
    });        

    // When `b64` is ready, I want to return it
    return b64;
");

1 Ответ

2 голосов
/ 18 апреля 2019

Это одна возможность. Я предполагаю, что это работает с сумраком / селеном также. Подсказка в том, что функция onload является в основном обратным вызовом, поэтому мы хотим использовать этот обратный вызов для разрешения обещания. Если вам нужен синхронизирующий код, async / await может сделать это и для вас, но конечный результат тот же, обещание возвращается, поэтому вы можете продолжить цепочку обещаний.

fetch(url)
    .then(r => r.blob())
    .then(blob => new Promise(( resolve ) => {
        var reader = new FileReader();
        reader.onload = function() {
            var b64 = reader.result.replace(/^data:.+;base64,/, '');
            resolve( b64 );
        };
        reader.readAsDataURL(blob);
    })
    .then( b64 => {
        // do something with b64
    });

Это означает, что вы не можете вернуть его к внешнему $b64 =.

Edit: Так что вместо

$b64 = fetch(url)
  .then( response => ... )
  .then( blob => ... )
  .then( image => ... );
renderImage( $b64 );

Вы хотели бы сделать

fetch(url)
  .then( response => ... )
  .then( blob => ... )
  .then( image => ... )
  .then( renderImage );

Или:

var $b64 = fetch(url)
  .then( response => ... )
  .then( blob => ... )
  .then( image => ... );
$b64.then( renderImage );

Редактировать 2:

Не ждите фактического Обещания, дождитесь, пока результат обещания не появится на экране, поэтому, согласно документам в сумерках, вы даете обещание 5 секунд для разрешения, прежде чем сумерки выдают ошибку.

Если Promise отобразит результат на странице, попробуйте обнаружить изменение в теге изображения, к которому будет отображаться изображение.

$dusk->script("
    fetch(url).then(r => r.blob()).then(blob => {
        var reader = new FileReader();
        reader.onload = function() {
            var b64 = reader.result.replace(/^data:.+;base64,/, '');
            document.querySelector( 'body' ).classList.add( 'loaded_image' );
        };
        reader.readAsDataURL(blob);
    });        
");

$dusk->waitUntil('body.loaded_image');

Решение:

$dusk->script('
     var url = document.getElementById("img_file").getAttribute("src");

     fetch(url)
         .then(r => r.blob())
         .then(blob => new Promise(( resolve ) => {
             var reader = new FileReader();
             reader.onload = function() {
                 var b64 = reader.result.replace(/^data:.+;base64,/, "");
                 resolve( b64 );
             };
             reader.readAsDataURL(blob);
         }))
        .then( b64 => {
            $("body").append(`<input id="b64string" value="${b64}">`);
         });
');

// wait until ajax to be finished
$dusk->waitUntil("!$.active", 30);

$b64Img = $dusk->script("return document.getElementById('b64string').value;"); // this returns array

dd($b64Img[0]); // works!
...