2016-06-21 2 views
1

저는 웅변적인 자바 스크립트를 사용하고 promise.all을 구현해야합니다. 여기 내 해결책이있다.javascript 구현이 promise.all 작동하지 않습니까?

function all(promises) { 
    return new Promise(function(success, fail) { 
    var results = []; 
    var failed = false; 
    promises.forEach(function(promise) { 
     promise.then(function(result) { 
     results.push(result); 
     }, function (error) { 
     failed = true; 
     fail(error); 
     }); 
    }); 
    if (!failed) 
     success(results); 
    }); 
} 

다음은 내가 수행중인 테스트입니다. []이 있어야한다

[1, 2, 3] : []

우리가해야 그것이이해야 할 []

를 출력하는 것 becuase

// Test code. 
all([]).then(function(array) { 
    console.log("This should be []:", array); 
}); 
function soon(val) { 
    return new Promise(function(success) { 
    setTimeout(function() { success(val); }, 
       Math.random() * 500); 
    }); 
} 
all([soon(1), soon(2), soon(3)]).then(function(array) { 
    console.log("This should be [1, 2, 3]:", array); 
}); 
function fail() { 
    return new Promise(function(success, fail) { 
    fail(new Error("boom")); 
    }); 
} 
all([soon(1), fail(), soon(3)]).then(function(array) { 
    console.log("We should not get here"); 
}, function(error) { 
    if (error.message != "boom") 
    console.log("Unexpected failure:", error); 
}); 

내 코드는 분명 잘못된 것입니다 여기에 오지 마시오

첫 번째 것은 유일한 것입니다. 내 결함이보기에서 나는이 작품을 쓴 여기에서 찾을 수 있습니다 내용과 기본적으로 동일 실제 솔루션 : http://eloquentjavascript.net/code/#17.2

왜 내 코드가 작동하지 않는 이유는 무엇입니까? 그게 뭐가 잘못 됐어?

+3

@AliTorabi이 바보하지 마십시오 : 내 솔루션에서 나는이 변수 count 이름.때로는 프로그래밍 및 언어 작업에 대한 이해를 높이기 위해 휠을 다시 발명하는 것이 중요합니다. –

+0

@AliTorabi 학습 운동으로서 나는 그것을 잘 이해하기 위해 공통된 기능을 재 구현하는 것이 좋다. 내 이해는 이것이 OP의 목표라는 것입니다. – Timo

+0

나는 더 이상 얼간이가 아니다. 코드와 질문에 대한 작업 –

답변

0

당신은

if (!failed)     
    success(results); 

너무 빨리 도달했다. 모든 약속이 완료되고 그것이 끝난다면 모든 것이 해결됩니다.

function all(promises) { 
    return new Promise(function(success, fail) { 
     var results = []; 
     var failed = false; 
     promises.forEach(function(promise) { 
      promise.then(function(result) { 

       results.push(result); 

       if (results.length == promises.length) { 
        if (!failed) 
         success(results); 
       } 
      }, function (error) { 

       failed = true; 
       fail(error); 
      }); 
     }); 


    }); 
} 

당신의 기능을 시험 :

all([soon(1), fail(), soon(3)]).then(function(array) { 
    console.log("We should not get here"); 
}, function(error) { 
    console.log("Fail"); 
    if (error.message != "boom") 
     console.log("Unexpected failure:", error); 
}); 

그러나, 아직 결과 순서의 부족이있다.

+0

주문이 없으면서도 빈 입력에 대해서는 작동하지 않습니다. – Bergi

1

forEach은 동기식이므로 약속이 해결되기 전에 if (!failed) 문이 실행됩니다. 다음과 같은 작업을 수행 할 수 있습니다

function all(promises) { 
    var results = [], 
     left = promises.length; 
    if (!left) { 
    return Promise.resolve(results) 
    } 
    return new Promise((res, rej) => { 
    promises.forEach((p, i) => { 
     Promise.resolve(p).then(x => { 
     results[i] = x 
     left -= 1 
     if (left === 0) { 
      res(results) 
     } 
     }, rej) 
    }) 
    }) 
} 

당신은 예를 들어, 순서를 유지할 수있는 스파 스 배열을 사용 :

다른 사람이 언급 한 것처럼
function timeout(n) { 
    return new Promise((res) => { 
    setTimeout(() => { 
     res(n) 
    }, n) 
    }) 
} 

var pa = timeout(200) 
var pb = timeout(300) 
var pc = timeout(100) 

// success 
all([pa, pb, pc]).then(console.log).catch(console.log) //=> [200, 300, 100] 


// error 
var pd = Promise.reject('error') 

all([pa, pb, pc, pd]).then(console.log).catch(console.log) //=> error 
+0

이것은 마지막 약속이 성취 될 때만 작동하는 것 같습니다. 빈 입력에도 작동하지 않습니다. 그리고 단순화를 위해'catch '없이'.then (..., rej)'을 권합니다. – Bergi

+0

아, 당신은 @Bergi가 옳습니다. 너무 나았습니다. – elclanrs

+0

내 편집 내용을 확인하십시오. 이번에는 모든 사례를 다룰 수 있기를 바랍니다. – elclanrs

0

, 당신의 .forEach 즉시, 당신의 약속은 해결 한이 완료되기도 전에. .forEach의 각 약속에 대해 비동기 계산을 완료하는 데는 일정한 시간이 걸립니다. 이 exercise의 경우 시간은 Math.random() * 5000입니다.

따라서 각 반복에서 최종 결과는 "약속 됨"이며 .forEach이 계속됩니다. 그래서 빈 배열을 얻습니다 : []. .forEach은 귀하의 약속이 해결되기 전에 완료되었습니다.

당신이하고 싶은 일은 해결되는 모든 약속을 추적하는 것입니다. 그리고 세 가지 해결 된 약속이있는 즉시 results 배열에서 귀하의처리기로 전화하십시오. 각 약속의 .then()에 전달 된 핸들러 외부에서 클로저 변수를 유지하여이 작업을 수행 할 수 있습니다. 각 약속이 완료되면 해당 변수를 증가시킬 수 있습니다.

function all(promises) { 
    return new Promise(function(success, fail) { 
    if (promises.length === 0) { 
     return success([]); 
    } 
    const results = []; 
    let count = 0; 

    for (let i = 0; i < promises.length; i++) { 
     promises[i].then(val => { 
     results[i] = val; 
     count++; 

     if (count === promises.length) { 
      return success(results); 
     } 
     }).catch(err => fail(err)); 
    } 
    }); 
} 
관련 문제