等待方法任务完成后再进行其他操作

时间:2020-04-25 20:33:28

标签: javascript

我有一个带有方法的类...其中一个实际上包含获取以获取svg文件的方法。那里什么都没有。 问题实际上不在于类,而是在使用时。

我有一个方法getDataFromFile(url),我将它传递给我的SVG url,它可以完成很多工作。问题是...当我使用它时,如果我紧随其后调用另一个方法,甚至只是console.log ...因为它还没有影响文件,我在显示该文件的地方得到了“ undefined”对象。

当然,如果我设置了一个超时,它可以工作,但这意味着它之后的所有内容都必须处于超时状态……我也可以在调用它的方法中很好地设置一个超时,但是随后这会也变得异步。

我尝试了很多事情,但我并没有真正得到承诺和类似的东西,所以...我完全被困在那里!

这是我的代码的(非常)简化版本,我知道它远非最佳(我是一个初学者),但无论如何这里都是这样:

var ParentClass = function ()
{
    // Attributes and stuff

    this.paths = [];
}


var MyClass = function ()
{
    ParentClass.call( this );
}


MyClass.prototype.getInlineDOMdata = function ( selector )
{
    // Stuff going on...

    let querySelector = document.querySelectorAll( selector + " path" );

    for ( let i = 0; i < querySelector.length; i++ )
    {
        this.paths.push(
            {
                name: querySelector[ i ].id,
                color: querySelector[ i ].style.fill,
                pathData: querySelector[ i ].attributes.d.value
            }
        );
    }

}


MyClass.prototype.getInlineData = function ( inlineCode )
{
    let domTarget = document.querySelector( "body" );

    domTarget.innerHTML += `<div class="placeholder">${ inlineCode }<div>`;

    let domContainer = document.querySelector( ".placeholder" );

    // Stuff going on...

    this.getInlineDOMdata( ".placeholder svg" );

    domContainer.remove();
}


MyClass.prototype.getDataFromFile = function ( url )
{
    fetch( url )
        .then( response => response.text() )
        .then( data => this.getInlineData( data ));
}

程序方面看起来像这样:

document.addEventListener( "DOMContentLoaded", loadComplete );

function loadComplete ()
{
    var test = new MyClass();
    test.getInlineData( `
     <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 195 82">
             <!--Some SVG code -->
     </svg>
      ` );
     console.log( test.paths[ 0 ] ); // Object { name... }
     console.log( test.paths.length ); // 4


    test.getInlineDOMdata( "svg" );
    console.log( test.paths[ 0 ] ); // Object { name... }
    console.log( test.paths.length ); // 4  */

    test.getDataFromFile( "https://upload.wikimedia.org/wikipedia/en/c/ce/SVG-logo.svg" );
    console.log( test.paths[ 0 ] ); // undefined
    console.log( test.paths.length ); // 0

    setTimeout( function ()
    {
        console.log( test.paths[ 0 ] ); // Object { name... }  
        console.log( test.paths.length ); // 4
    }, 1000 );
}

因此,当我使用getInlineData时,它可以工作。 当我使用getInlineDOMdata时,它可以工作。 当我使用getDataFromFile时,它不会!但是,如果我放了一个计时器,它就可以了。

我发现这确实是“肮脏的”,我迫切希望找到一个合适的解决方案,在这里我可以直接调用其他方法直接调用此方法!

编辑:已解决!

使用async / await,只需将我的方法getDataFromFile更改为

MyClass.prototype.getDataFromFile = async function ( url )
{
    let response = await fetch( url )
        .then( response => response.text() );

    await this.getInlineData( response );
}

和程序方面,在async函数之前添加loadComplete,并在await行之前添加test.getDataFromFile( "urlToSvg.svg" );解决了我的问题!

感谢Leftium提供的伟大的教学语言(tutorial),这使我终于明白了诺言的实现方式

1 个答案:

答案 0 :(得分:1)

使用async / await。这些关键字基本上是诺言的语法糖,因此了解诺言的工作方式将非常有帮助。

这是一个很棒的tutorial,它使用Promise遍历了一个异步示例,然后将其转换为async / await语法。相关报价:

好消息是JavaScript允许您编写 伪同步代码,用于描述异步计算。异步 函数是隐式返回promise的函数,并且可以 在其主体中,以看起来同步的方式等待其他承诺。

...

在异步函数中,可以将await放在前面 表达等待解决的诺言,然后继续 功能的执行。

这样的函数不再像常规的JavaScript函数那样运行 从头到尾一口气。而是可以将其冻结在任何位置 等待的时间点,可以在以后的时间恢复。