2014-02-12 1 views
3

배열의 모든 항목에 대해 동적으로 함수를 실행해야하지만, Array.forEach이 순서대로 실행되며 비동기로 실행해야합니다.Array.forEach를 Q.js와 비동기로 변환하는 방법은 무엇입니까?

var promises = []; 

items.forEach(function(item) { 
    var promise = function() { 
     return Q.fcall(function() { 
      doSomething(item); 
     }); 
    }; 
    promises.push(promise()); 
}); 

Q.all(promises).then(function() { 
    otherFunction(datacontext.mainList); //use datacontext.mainList filled. 
}); 

그러나 실행은 순서대로 항상 내가 병렬로 실행을해야합니다

items.forEach(function(item) { 
    doSomething(item); 
}); 

나는이 시도합니다.

doSomething(item) 방법 :

function doSomething(item) { 
     var children = getChildren(item); //get data from local with manager.executeQueryLocally 
     var total = getTotal(children); //simple calculations 
     datacontext.mainList.push({ 
      name: item.firstName() + ' ' + item.lastName(), 
      total: total 
     }); 
    } 

저를 도와주세요.

+0

이 WebWorkers을 봐 도움이 되었기를 이야기하고, 자바 스크립트는 단일 스레드입니다. – OneOfOne

+0

당신은 items.forEach를 setTimeout에 넣을 수 있습니다. setTimeout (function() {(코드가 여기에옵니다)}, 1) –

+0

작업에 잘못된 도구를 사용하려고합니다. 약속은 동기 코드를 비동기 코드로 변환하는 도구가 아닙니다. 이들은 비동기 콜백 체인의 복잡성을 줄이는 수단입니다. –

답변

21

이 답변 doSomething 자체 비동기 작업이라고 가정 ...

promises.push(promise()); 

으로 ... 변경해보십시오. 즉, 이벤트 루프에 양보해야하고 한 번 이상 다른 이벤트를 기다려야합니다. doSomething이 동기이면 비동기식으로 작성할 때 이점이 없습니다.

복합 비동기 작업 영역에는 직렬 및 병렬 변형이 있습니다. 직렬 모델은 작업 (n)이 완료된 후에 만 ​​작업 (n + 1)이 시작되도록합니다. 병렬 모델은 처음에 모든 작업을 시작하고 모든 작업이 완료되면 완료됩니다. 이 두 가지 측면에서 나는 여러분에게 조언을 해줄 수 있습니다.

병렬에서는 doSomethingjobs에서 값을 받아 약속을 반환 가정, 배열지도 및 Q.all를 사용할 수 있습니다

return Q.all(jobs.map(doSomething)) 

직렬 순서로 작업을 수행하려면, 배열이 감소 사용합니다. 당신이 일련의 작업을 수행하지만, 첫 번째의 결과에 따라 다음 작업을 진행하려면

return jobs.reduce(function (previous, job) { 
    return previous.then(function() { 
     return doSomething(job); 
    }); 
}, Q()); 

, 당신은 기능을 구성 할 reduceRight를 사용할 수 있습니다.

return jobs.reduceRight(function (next, job) { 
    return function (previous) { 
     return doSomething(job).then(function (result) { 
      if (result.isGood(previous)) return result; 
      return next(result); 
     }); 
    }); 
}, function fallthrough(previous) { 
    throw new Error("No result was satisfactory"); 
})(); 

당신이 다음의 입력에 이전의 출력을 공급, 순서대로 실행해야 기능을 포함 된 배열이있는 경우, 당신은 훨씬 더 간결 reduce 사용할 수 있습니다.

return functions.reduce(Q.when, Q()); 

Q의 추가 정보의 튜토리얼 더 많은 사례를 설명하고 내가 https://github.com/kriskowal/q#tutorial

0

마치 반복문을 배열에 푸시 할 때 즉시 작성중인 약속을 실행하는 것처럼 보입니다.

promises.push(promise); 
+0

나는'promises.push (promise);로 테스트했지만,이 코드는'promises.push (promise());'는 약속을 이행하지 않았다.)'모든 약속을 순서대로 실행하십시오. – kuskunko

+1

doSomething (item) 메서드는 동기 메서드입니까? Q는 싱크 메서드를 asynch 메서드로 변환하지 않습니다. doSomething 함수는 비동기 적이어야합니다. – Jason

+0

예, 그렇습니다. 도와주세요. 비동기 메서드에서 doSomething (item)을 변환하는 방법은 무엇입니까? – kuskunko

관련 문제