2017-12-19 16 views
0

私はAPIコールを使用してデータを取得し、私のreduxストアを更新しています。次に、各API呼び出しの状態の変更を示します。プロミス。すべての約束を解決するためにいくつかreduxストアを更新することができませんでした

  1. API呼び出しを行う前に、成功したtrue
  2. としてisLoadingを設定するには、falseとしてisLoadingをリセット失敗しfalse
  3. としてisLoadingをリセットしtrueとしてisErrorを設定します。

私のコンポーネントには、以下の構造の3つの異なるレビュックスストアに格納された3つのAPIのデータが必要です。私のコンポーネントで

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

、私は

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を呼び出すために、次の使用私は以下のように負荷状態をチェックするためにselectorを書かれています。 getIsLoadingの値に基づいて

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

私はコンポーネントをレンダリングそうでない場合は、私のコンポーネントに積載状態を示します。

しかし、API呼び出しのいずれかが失敗したときに問題が発生することがあります。たとえば、loadBookは100ミリ秒で失敗し、そのときはbLoadingfalseに変更されますが、tLoadingはまだtrueです。bcz loadTeacher api呼び出しが完了していません。 Promise.all()以来、APIの呼び出しはloadTeacherは決して完了しませんでしたので、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); 
     }); 
    }); 
}; 

" '

+0

これは、statusというメンバを持つオブジェクトで拒否された場合にのみ機能します。約束事のどれかが未定義(undefined.status'を実行しようとしている)で拒否したり解決したりすると、常にクラッシュします。失敗しない 'Promise.all'という考えは良いですが、あなたはこのようにしてはいけません(私の答えを見てください)。 – HMR

0

loadbookが失敗した場合、loadTeacherは停止せず、Promise.allの解決ハンドラは単に呼び出されません。

あなたがtLoading(解決で偽に設定)とbLoading(キャッチで設定)の両方が偽で、次のコードで見ることができます

:切り取らとしてそれはスタックオーバーフローに地獄のようにバグがあるので

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)); 
    } 
) 
関連する問題