2017-05-28 4 views
0

Webサイトに表示されるいくつかのJSONに保存されているフォーラムデータをロードしています。データ自体は、スレッドデータとユーザーデータの2種類のファイルに分かれています。Promise.allはあまりにも早く解決します

// threads/135.json 
{ 
    "title": "Thread Title", 
    "tid": 135, 
    "posts": [ 
    { 
     "pid": 1234, 
     "timestamp": 1034546400, 
     "body": "First forum post", 
     "user": 5678 
    }, 
    { 
     "pid": 1235, 
     "timestamp": 103454700, 
     "body": "Reply to first forum post", 
     "user": 9876 
    } 
    ] 
} 

スレッドデータがロードされると、ユーザーIDに基づいてユーザーデータが読み込まれます。

// user/1234.json 
{ 
    "id": 1234, 
    "name": "John Doe", 
    "location": "USA" 
} 

実際のコードがGoogle's Introduction to Promisesに基づいていますが、それはこのようになります関数になって:

export default function loadData(id) { 

    var didLoadUser = []; 
    var dataUsers = {}; 
    var dataThread = {}; 

    getJSON('./threads/' + id + '.json').then(function(thread) { 
    dataThread = thread; 

    // Take an array of promises and wait on them all 
    return Promise.all(
     // Map our array of chapter urls to 
     // an array of chapter json promises 
     thread.posts.map(function(post) { 
     if (post.user > 0 && didLoadUser.indexOf(post.user) === -1) { 
      didLoadUser.push(post.user); 
      return getJSON('./users/' + post.user + '.json') ; 
     } 
     }) 
    ); 
    }).then(function(users) { 
    users.forEach(function(user) { 
     if (typeof user !== 'undefined') { 
     dataUsers[user.id] = user; 
     } 
    }); 
    }).catch(function(err) { 
    // catch any error that happened so far 
    console.error(err.message); 
    }).then(function() { 
    // use the data 
    }); 
} 

// unchanged from the mentioned Google article 
function getJSON(url) { 
    return get(url).then(JSON.parse); 
} 

// unchanged from the mentioned Google article 
function get(url) { 
    // Return a new promise. 
    return new Promise(function(resolve, reject) { 
    // Do the usual XHR stuff 
    var req = new XMLHttpRequest(); 
    req.open('GET', url); 

    req.onload = function() { 
     // This is called even on 404 etc 
     // so check the status 
     if (req.status == 200) { 
     // Resolve the promise with the response text 
     resolve(req.response); 
     } 
     else { 
     // Otherwise reject with the status text 
     // which will hopefully be a meaningful error 
     reject(Error(req.statusText)); 
     } 
    }; 

    // Handle network errors 
    req.onerror = function() { 
     reject(Error("Network Error")); 
    }; 

    // Make the request 
    req.send(); 
    }); 
} 

コード自体が私のコンポーネントのcomponentWillMount関数の中で呼び出される関数に変換する前に、うまく働きました。

componentWillMount: function() { 
    this.setState({ 
     data: loadData(this.props.params.thread) 
    }) 
} 

私はPromise.allは、スレッドのデータをロードした後、ユーザーデータのいずれかをロードする前に解決しますように見えますので、誤差は、関数自体内にあると思います。

私は最近、約束を使用し始めたので、私の知識はむしろ基本的なものです。私は間違って何をしていますか?私は別の約束の中に主要な機能を包む必要がありますか?

+0

どのように関数を呼び出しますか/結果はどこにありますか? –

+0

あなたの約束がうまく見える、私は彼の答えに記載されているように@問題視覚化(反応)と問題だと思う。 – Hosar

+0

'loadData()'は約束を返す必要があり、 'loadData()'の呼び出し側は結果にアクセスするために約束を使用する必要があります。 – jfriend00

答えて

2
this.setState({ 
    data: loadData(this.props.params.thread) 
}) 

データは単に同期方法で、時間内に準備されていないとして、あなたは上記のように非同期呼び出しから戻ることはできません。あなたはそのためのコードは、例えばのようになります、約束を返す:

loadData(this.props.params.thread) 
.then((data)=> { 
    this.setState({ 
    data, 
    }) 
}) 

注: それは仕事を得るためには、あなたがloadDataから復帰約束する必要があり、それゆえ:

... 
return getJSON(.. 
... 
関連する問題