这可能很简单,但我找不到办法。 我有一个数组,我想为每个数组值执行一些操作但仅在前一个完成后执行。 让我说我有一个数组[1,2,3,4,5],我想添加一个名为“picture”+ i +“。jpg”的图片的img标签,如果图片文件不存在 - 使用默认图片,用这个img做更多的动作,只有在完成所有操作后,再做一次“foreach”。
我正在研究承诺,但仍然无法弄明白。 问题是它不仅仅是一个异步动作(ajax或get),而是一些不同的动作。
由于
答案 0 :(得分:0)
不确定这是否是您所需要的。但我确实必须解决几个异步对话框的情况,所以这应该工作。请注意,这需要支持Promise
的浏览器或要求您使用Promise垫片。
var items = [1,2,3,4,5];
var chainObj = {}; // Set this up if you need to communicate info to subsequent items. Or you need some form of "reduce" capability.
var promise = Promise.resolve(accumObj); // The initial promise.
for (var i = 0; i < items.length; i++){
var currItem = items[i];
promise = promise.then(function(accumObj){
if (/*Need Async Stuffs*/){
return new Promise(function(resolve, reject){
/*perform some async stuff for the currItem. Once they're done, update accumObj and invoke the below function*/
resolve(accumObj);
});
} else {
/* Perform non-async stuffs for currItem, update accumObj as needed. */
return accumObj; // Return the accumObj for the next step.
}
});
}
promise.then(/*Put call back to finish up anything else that's left*/);
以上将保证每个“项目”在前一项完成之前不会开始处理,只要您在完成所有异步操作后只调用“resolve”(如果需要,在每个循环中将多个promise链接在一起)根据需要)。
简而言之,上面的调用会创建一长串承诺,如下面的伪代码:
Promise.resolve(chainObj)
.then(/*Process items[0]*/)
.then(/*Process items[1]*/)
.then(/*Process items[2]*/)
.then(/*Process items[3]*/)
.then(/*Process items[4]*/)
.then(/*Process for when everything is done*/)
每个流程步骤要么立即解析(else
部分,也称为非异步路径),要么在某些异步操作(/*Need Async stuffs*/
路径)后解析。并且后续流程步骤仅在前一流程步骤结算后才会启动。 accumObj
允许您累积每个步骤的结果并将其传递给下一步。
代码块中的最后promise.then
是您处理完所有内容后可以执行任何最终操作的地方。
CAVEAT:上面的示例代码不处理任何错误/异常。
编辑#1:
要处理相对复杂的操作,请将promise = promise.then...
块修改为此。
promise = promise.then(function(accumObj){
// Start running you async stuffs
var promises = [];
promises.push(new Promise(function(resolve, reject){
// Async function #1. Invoke resolve when the async function completes (simplest solution, pass "resolve" to whatever callback the
// The async fucntion uses.
});
promises.push(new Promise(function(resolve, reject){ // Async function #2. });
promises.push(new Promise(function(resolve, reject){ // Async function #3. });
// ...
promises.push(new Promise(function(resolve, reject){ // Async function #Last. });
// Do synchronous function here.
return Promise.All(promises).then(function(results){
// Process the results from your async calls, udpate accumObj as needed.
return accumObj;
});
});
以上操作是在处理同步函数之前为当前项启动所有异步函数(让异步并行运行)。 return Promise.All(promises).then(function(results){return accumObj;});
返回执行以下操作的另一个承诺。
promises
中的每个承诺都得到解决。then
回调中的函数(results[0]
是已解析的值或promises[0]
,依此类推)。accumObj
,它将成为return Promise.All(promises).then(function(results){return accumObj;});
的解析值。答案 1 :(得分:0)
我最终得到以下代码
$('.imageloaderbutton').on('click', function(){
var defaultimage='http://mysite/images/none.gif';
var ds={}; var a=[{'name':'test1'},{'name':'test5'},{'name':'test3'},{'name':'test4'}], i=a.length;
var addimagefromarray = function(n){
console.log('deferring '+n ); ds[n]=$.Deferred(); var imgn=a[n].name
var $avt=$('<img/>')
.error(function(){ $(this).attr("src", defaultimage); })
.attr('src', 'http://mysite/images/'+imgn+'.jpg')
.load(function(){
$('.imagesdiv').append($(this));
ds[n].resolve();
if(n<(i-1)){ds[n].done(li(n+1));}
});
}
li(0);
});
但是感谢ShuberFu的答案 - 这非常有用