2017-03-16 96 views
1

按照这个示例如何摆脱循环中的一系列异步操作?

Dojo FAQ: How can I sequence asynchronous operations?

function doNext(previousValue) { 
    var dfd = new Deferred(); 

    // perform some async logic; resolve the promise 
    setTimeout(function() { 
     var next = String.fromCharCode(previousValue.charCodeAt(previousValue.length - 1) + 1); 
     dfd.resolve(previousValue + next); 
    }, 50); 

    return dfd.promise; 
} 

var promise = doNext('a'); 

for (var i = 0; i < 9; i++) { 
    promise = promise.then(doNext); 
} 

promise.then(function (finalResult) { 
    // 'doNext' will have been invoked 10 times, each 
    // invocation only occurring after the previous one completed 

    // 'finalResult' will be the value returned 
    // by the last invocation of 'doNext': 'abcdefghijk' 
    console.log(finalResult); 
}); 

如何打破循环 - 即停止处理时doNext符合一定条件的后续doNext函数调用 - 例如停车时,下一个字符是“d '并将计算值返回到该点?

编辑:到目前为止我尝试使用deferred cancel()方法,但它只是杀死进程,并且什么都不返回。

setTimeout(function() { 
    var next = String.fromCharCode(previousValue.charCodeAt(previousValue.length - 1) + 1); 
    if(previousValue + next == 'abc') 
     dfd.cancel('abc'); 
    else 
    dfd.resolve(previousValue + next); 
}, 50); 

回答

1

您可以通过检查承诺返回的值并决定是否再次调用异步请求来做到这一点。它不像您在for循环中添加break。但结果将是你的愿望。

所有9 promise.then将被调用,但doNext将不会被调用9次。以下是相同的摘录。

for (var i = 0; i < 9; i++) { 
    promise = promise.then(function(val){ 
     return val === "abcd" ? val : doNext(val); 
    }); 
} 

您可能认为这不存在循环。这是因为循环在调用回调函数之前完成。但是,而不是调用异步函数,回调函数将简单地返回值。这会导致循环快速完成。下面是一个JSBin的链接,我已经增加了超时时间,你会看到,最初它会花费更多的时间直到返回所需的结果,然后很快退出。

https://jsbin.com/qiwesecufi/edit?js,console,output

另外,地方,你可以做检查,是doNext功能本身。

function doNext(previousValue) { 
    var dfd = new Deferred(); 

    if(previousValue === "abcd") 
     return previousValue; 

    // perform some async logic; resolve the promise 
    setTimeout(function() { 
     var next = String.fromCharCode(previousValue.charCodeAt(previousValue.length - 1) + 1); 
     dfd.resolve(previousValue + next); 
    }, 1000); 

    return dfd.promise; 
} 

希望这对我很有帮助。

1

当您始终要处理所有项目(或同时决定需要多少项目)时,您应该只使用reduce(或promise = promise.then(doNext))循环方法。

要循环的任意次数,并在任何步骤爆发,递归是更好的方法:

function wait(t, v) { 
    var dfd = new Deferred(); 
    // asynchronously resolve the promise 
    setTimeout(function() { 
     dfd.resolve(v); 
    }, t); 
    return dfd.promise; 
} 

function doNext(previousValue) { 
    var next = String.fromCharCode(previousValue.charCodeAt(previousValue.length - 1) + 1); 
    return wait(50, previousValue + next); 
} 

function loop(v, i) { 
    if (i <= 0) return when(v); 
    if (v == "abc") return when("abc"); 
    return doNext(v).then(function(r) { 
     return loop(r, i-1); 
    }); 
} 

loop('a', 9).then(function (finalResult) { 
    console.log(finalResult); 
}); 
+0

我是想你的榜样,但两个问题1) - 什么是“何时”? 2)单步执行代码,它从不将最终结果写入控制台,是否应该这样做? – erotavlas

+0

['when when](https://dojotoolkit.org/reference-guide/1.10/dojo/when.html)似乎是dojo写作方式['Promise.resolve'](https://developer.mozilla .ORG/EN-US /文档/网络/的JavaScript /参考/ Global_Objects /无极/解析)。关于最终结果,是的,它绝对应该,尽管我没有测试过代码(并且只是注意到我忘记了通过'i')。 – Bergi