2017-12-19 19 views
0

API 호출을 사용하여 데이터를 가져오고 내 redux 저장소를 업데이트합니다. 다음은 각 API 호출에 대한 상태 변경입니다.Promise.all 일부가 redux 저장소를 업데이트하지 못한 경우에도 모든 약속을 해결합니다.

  1. API 호출을하기 전에 성공 true
  2. isLoading 설정은 falseisLoading를 다시 실패하면 false
  3. isLoading를 재설정하고 trueisError을 설정합니다.

내 구성 요소에는 아래의 구조와 같이 3 개의 다른 redux 저장소에 저장된 3 개의 API의 데이터가 필요합니다. 내 구성 요소에서

store: { 
    book: { 
     isLoading: false, 
     isError: false, 
     data: {} 
    }, 
    teacher: { 
     isLoading: false, 
     isError: false, 
     data: {} 
    }, 
} 

는, 나는 다음과 같이 로딩 상태를 확인하기 위해 selector를 작성했습니다

componentWillMount() { 
    const { 
     loadBook, 
     loadTeacher, 
    } = this.props; 

// all these load functions dispatch action which returns Promise for async API call using `fetch` 
    const apiCalls = [ 
    loadBook(), 
    loadTeacher(), 
    ]; 

    Promise.all(apiCalls); 

    } 

API를 호출하려면 다음을 사용합니다.

export const getIsLoading = createSelector([ 
    getIsBookLoading, 
    getIsTeacherLoading, 
], 
    (bLoading, tLoading) => (
    bLoading || tLoading 
) 
); 

getIsLoading의 값을 기준으로 내가 요소를 렌더링, 그렇지 않으면 내 구성 요소의로드 상태를 보여 않습니다.

그러나 API 호출 중 하나가 실패하면 문제가 발생합니다. 예를 들어, loadBook은 100ms에서 실패하고 bLoadingfalse으로 다시 변경되지만 tLoading은 여전히 ​​true입니다. bcz loadTeacher API 호출이 완료되지 않았습니다. Promise.all() 이후 모두 또는 아무 것도하지 않으므로 loadTeacher에 대한 API 호출이 완료되지 않으므로 tLoading stas true.

Promsie.all은 더티 상태를 정리할 수 없도록 일부 호출이 실패하더라도 해결할 수 있습니까?

+0

예, 그렇기 때문에'Promise.all() '이 종료 된 것입니다. 다른 많은 모듈에서 사용되는 API 호출 논리 bcz를 변경할 수 없습니다. 내가 어떻게 내 편에서 처리 할 수 ​​있을지 생각하고 있었다. – joy

답변

-1

전용 라이브러리 (일부 라이브러리가 있습니다. 이름이 기억되지 않습니다. -_-)를 사용하거나 직접 실행해야합니다. 그리 어렵지 않습니다.

내가 그 일을 어떤 코드가 수행

(- 귀하의 약속 array-) 항상 해결하고 당신에게 당신이 분석 할 수 있습니다 실패한 약속을 포함하는 배열을 보내드립니다 MyPromise.when를 호출
var MyPromise = {}; 

MyPromise.getDefaultPromise = function() { 
    return new Promise(function (resolve, reject) { resolve(); }); 
}; 

MyPromise.when = function (promises) { 
    var myPromises = []; 
    for (var i = 0; i < promises.length; i++) { 
     myPromises.push(MyPromise.reflect(promises[i])); 
    } 
    return Promise.all(myPromises). 
    then(function (oResult) { 
     var failure = oResult.filter(function (x) { return x.status === 'error';}); 
     if (failure.length) { 
      return MyPromise.fail(failure); 
     } 
     return MyPromise.getDefaultPromise(); 
    }); 
}; 

MyPromise.fail = function (failure) { 
    return new Promise(function (resolve, reject) { 
     reject(failure); 
    }); 
}; 

MyPromise.reflect = function (promise) { 
    return new Promise(function (resolve) { 
     promise.then(function (result) { 
      resolve(result); 
     }). 
     catch(function (error) { 
      resolve(error); 
     }); 
    }); 
}; 

' then '

+0

status라는 멤버가있는 객체로 거부하는 경우에만 작동합니다. 어떤 약속이 undefined (undefined.status'를하려하고 있습니다)를 거부하거나 해결하면 항상 충돌합니다. 실패하지 않는'Promise.all'의 아이디어는 좋지만이 방법으로해서는 안됩니다 (내 대답 참조). – HMR

0

loadbook이 실패하면 loadTeacher가 중지되지 않고 Promise.all의 해결 핸들러가 호출되지 않습니다.

당신은 모두 tLoading은 (캐치에서 설정)과 bLoading (해결에서 false로 설정) 다음 코드에서 볼 수는 거짓 :

var bLoading = true; 
var tLoading = true; 
const loadBook = 
() => Promise.reject("load book rejects"); 
const loadTeacher = 
() => Promise.resolve("load book rejects") 
    .then(()=>tLoading=false); 
Promise.all([ 
    loadBook() 
    .catch(
    (err)=>{ 
     bLoading=false; 
     return Promise.reject(err); 
    } 
), 
    loadTeacher() 
]) 
.catch(
()=>console.log("bLoading:",bLoading,"tLoading:",tLoading) 
); 

수 없습니다 냈다으로 그 스택 오버플로에서 지옥 같은 버그가 있기 때문에 삽입 계속 실패하지만 콘솔에서 코드를 실행할 수 있습니다.

Promise.all을 제대로 사용하려면 Ash Kander가 올바른 방향으로 가고 있지만 유효한 해결 값과 거부를 구분하는 방법은 무엇입니까?명시 적 실패 값을 만드는 것이 더 좋습니다.

const Fail = function(reason){this.reason=reason;}; 
Promise.all(
    [ 
    loadBook, 
    loadTeacher 
    ].map(
    fn=> 
     fn() 
     .catch(
     (err)=> 
      new Fail(err) 
    ) 
) 
)//this will never fail 
.then(
    ([book,teacher])=>{ 
    console.log("did book fail?",(book&&book.constructor===Fail)); 
    console.log("did teacher fail?",(teacher&&teacher.constructor===Fail)); 
    } 
)