执行javascript脚本并等待promise被解析以返回值

执行javascript脚本并等待promise被解析以返回值,javascript,php,laravel,selenium,laravel-dusk,Javascript,Php,Laravel,Selenium,Laravel Dusk,我想运行一个脚本,等待承诺返回值 $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:.

我想运行一个脚本,等待承诺返回值

$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);
});
我想返回
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;
");

这是一种可能性。我认为它也适用于黄昏/硒。 线索是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=

编辑: 所以不是

$b64 = fetch(url)
  .then( response => ... )
  .then( blob => ... )
  .then( image => ... );
renderImage( $b64 );
你想做什么

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

编辑2:

$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!
不要等待实际的承诺,等待承诺的结果显示在屏幕上,因此根据Dash文档,在Dash抛出错误之前,您给承诺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!
$dash->script('
var url=document.getElementById(“img_文件”).getAttribute(“src”);
获取(url)
.then(r=>r.blob())
.然后(blob=>新承诺((解决)=>{
var reader=new FileReader();
reader.onload=函数(){
var b64=reader.result.replace(/^data:.+;base64,/,“”);
决议(b64);
};
reader.readAsDataURL(blob);
}))
。然后(b64=>{
$(“正文”)。追加(``);
});
');
//等待ajax完成
$黄昏->等待直到(!$.active),30);
$b64Img=$dusk->script(“return document.getElementById('b64string').value;”);//这将返回一个数组
dd($b64Img[0]);//作品

的可能副本,因此基本上您希望将reader.onload()包装在另一个承诺中并返回该承诺。然后onload()可以解决这个问题。所以你可以用另一个继续这个promsie链。然后()我想不出来,这就是我问的原因。如何将
reader.onload=function(){}
包装到另一个承诺中?如果我最后写了return b64(在最后一个
then()
)之后),它不就是返回undefined吗?我不需要返回最后一个
then()
?这就是问题所在,除非使用异步/等待语法,否则无法返回到外部变量。您需要在
处理程序中使用$b64执行任何操作。然后()
处理程序。最简单的方法就是将一个函数传递给
。然后()
,它将执行您想用
$b64=..
执行的任何操作。或者使用async/await语法重写它,这样返回就可以像writetten一样工作。也许黄昏也有一些语法糖,让我们先解包,然后再解析结果。这就是我感到困惑的地方。异步/等待语法是什么意思?我很困惑如何做到这一点。我看了看黄昏,但——所以我以后也无法接近它;因此,需要在
$dash->script()
中执行此操作。哦,您的意思是,在最后一个
then()
中,调用另一个将返回b64变量的函数-让我尝试一下,如果混淆,我不会使用它。最终,async/await只是编写承诺的语法糖。