在Javascript中构建更长操作的序列

时间:2017-07-02 21:13:14

标签: javascript

考虑一系列步骤,这些步骤需要在准备繁重的网页时执行:

<Window x:Class="wpftest.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:wpftest"
    mc:Ignorable="d"
    Title="MainWindow" Height="350" Width="525">
<Grid>

    <Border Opacity="0.5" Grid.ZIndex="3">
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto"/>
                <RowDefinition Height="Auto"/>
            </Grid.RowDefinitions>
            <MediaElement Height="300" Width="300"
                   Source="c:\us\Resources\loader.gif" 
                   LoadedBehavior="Play" 
                   Stretch="Uniform" SpeedRatio="1" IsMuted="False" />
            <TextBlock Grid.Row="1" Text="Loading..." HorizontalAlignment="Center"/>

        </Grid>
    </Border>

    <!-- Controls -->
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
        <TextBox/>
        <Label Grid.Row="1" Content="Some Label"></Label>
        <TextBox Grid.Row="2"/>

    </Grid>

  </Grid>

每个步骤可能需要100毫秒到几秒的范围:但我们事先不确定每个步骤需要多长时间。

至少在step1(); step2(); .. stepk(); / Promise到达街道之前,我的理解是我们使用回调和await

但我们怎样才能避免这种情况迅速变得笨拙?按照以下顺序,我们有两个问题:

  • 如何在实际工作量达到两个数量级的范围内指定超时时间
  • 如何处理在下面显示的代码中传递参数 - setTimeout - 到嵌套函数调用

前两步(K):

argK

那么如何构建这些顺序步骤,以便我们不会在整个函数链中发送function step1(args1,args2,args3,..) { // do work for step1 using args1 setTimeout(function() {step2(args2,args3);}, [some timeout..]); } function step2(args2,args3,..) { // do work for step2 using args2 setTimeout(function() {step3(args3 [, args4, args5 ..]);}, [some timeout..]); } 不断增长的列表?

注意:对于某些情况,args可能是一种有用的方法:但我希望能够从本地文件系统提供服务,这显然排除了它们:

http://blog.teamtreehouse.com/using-web-workers-to-speed-up-your-javascript-applications

  

受限制的本地访问

     

如果直接提供网页,Web Workers将无法工作   来自文件系统(使用file://)。相反,你需要使用一个   本地开发服务器,如XAMPP。

2 个答案:

答案 0 :(得分:1)

没有承诺或异步等待,你必须做回调地狱风格

function step1(a,b,c){
  setTimeout(() => {
    step2():
  }
}

或者您可以将引用传递给下一步

如果step2依赖于step1的结果

function step1(a,b,c, done){
  setTimeout(() => {
    done(a,b,step3):
  }
}
function step2(d,e,done){
  setTimeout(() => {
    done(e):
  }
}

step1("cat","dog","mouse", step2);

如果您想手动将args传递给step2,并从step1

获取结果
function step1(a,b,c, done){
  setTimeout(() => {
    done(a):
  }
}
function step2(d,e,done){
  return function(step1a){
    setTimeout(() => {
      done(step1a, d):
    }
  }
}

step1("cat","dog","mouse", step2("d","e", step3);

如果没有Promisifying你的异步行动或实现你自己的承诺风格,这可能会很干净。

答案 1 :(得分:0)

我一直在阅读generator functions,看来它们可能是一个普通的JS解决方案。

Alex Perry wrote a great article及相关演示:

&#13;
&#13;
function step1() {
    setTimeout(function(){
        gen.next('data from 1')
    }, 500);
}

function step2(data) {
    setTimeout(function(){
        gen.next(`data from 2 and ${data[0]}`)
    }, 700);
}

function step3() {
    setTimeout(function(){
        gen.next('data from 3')
    }, 100);
}


function *sayHello() {
    var data = [];
    data.push(yield step1());
    data.push(yield step2(data));
    data.push(yield step3(data));
    console.log(data);
}

var gen = sayHello();

gen.next();
&#13;
&#13;
&#13;

在上面的示例中,每个异步请求都返回一个伪数据。每个连续步骤接收包含先前响应的数组,因此可以使用先前的响应。