2017-01-20 17 views
1

フェッチでサーバーからのデータを返すときに問題が発生しています。理由を理解できないようです。Fetch()が応答してサーバーからデータを返さない

サーバがJSONを返送する前に約束が解決されたと思っていたので、私は最近の約束を活用するためにモデルを更新しました。私は約束とAPIをフェッチするのは新しいので、私と一緒に耐える。

私もコールバックを戻すと に戻っPlayers.jsルートを私Player.findPlayer.create方法を入れて、完全にサーバー側の約束を避けるために喜んで。

プレーヤーモデル(約束を追加した後)

// require mongoose for data modeling 
import mongoose from 'mongoose'; 
import Q from 'q'; 

const Schema = mongoose.Schema; 

// define player schema 
const PLAYER_SCHEMA = new Schema({ 
    name: String, 
    score: Number 
}); 

PLAYER_SCHEMA.statics.createPlayer = (name, score) => { 
    const deferred = Q.defer(); 

    Player.create({ 
    name, 
    score, 
    }, (error, player) => { 
    if (error) { 
     deferred.reject(new Error(error)); 
    } 

    deferred.resolve(player); 
    }); 

    return deferred.promise; 
} 

PLAYER_SCHEMA.statics.getPlayers =() => { 
    const deferred = Q.defer(); 

    Player.find({}) 
    .sort({ 
     score: 'desc' 
    }) 
    .limit(5) 
    .exec((error, players) => { 
     if (error) { 
      deferred.reject(new Error(error)); 
     } 

     deferred.resolve(players); 
    }); 

    return deferred.promise; 
} 

let Player = mongoose.model('Player', PLAYER_SCHEMA); 

// first param is the singular name for the collection, 
// mongoose automatically looks for the plural version 
// so our db will have a 'players' collection 
export default Player; 

ルートこれらのエンドポイントをテスト

// dependencies 
import express from 'express'; 
import Player from '../models/player'; 

const ROUTER = express.Router(); 

ROUTER.post('/', (req, res) => { 
    const name = req.body.name; 
    const score = req.body.score; 
    const promise = Player.createPlayer(name, score); 

    promise.then((response) => { 
    res.status(201).json(response); 
    }).catch((err) => { 
    res.send(err) 
    }); 

}); 

ROUTER.get('/', (req, res) => { 
    const promise = Player.getPlayers(); 

    promise.then((response) => { 
    console.log(response); 
    res.status(200).json(response); 
    }).catch((err) => { 
    res.send(err) 
    }); 
}); 

export default ROUTER; 

はポストマンでは正常に動作しますので、私は問題を想定(約束を追加した後)サーバー上に存在しません。

これは私が問題があると思われるところです。

(AJAXメソッドが格納されている)Client.js

function createPlayer(playerData, onError, cb) { 
    return fetch('/api/players', { 
    method: 'post', 
    body: JSON.stringify(playerData), 
    headers: { 
     'Accept': 'application/json', 
     'Content-Type': 'application/json', 
    }, 
    }).then(checkStatus) 
    .then(cb) 
    .catch(onError); 
} 

function getPlayers(success, onError) { 
    return fetch('/api/players', { 
    headers: { 
     'Accept': 'application/json', 
     'Content-Type': 'application/json', 
    }, 
    }).then(checkStatus) 
    .then(parseJSON) 
    .then(success) 
    .catch(onError); 
} 

function checkStatus(response) { 
    if (response.status >= 200 && response.status < 300) { 
    return response; 
    } else { 
    const error = new Error(`HTTP Error ${response.statusText}`); 
    error.status = response.statusText; 
    error.response = response; 
    throw error; 
    } 
} 

function parseJSON(response) { 
    return response.json(); 
} 

const Client = { 
    createPlayer, 
    getPlayers 
}; 
export default Client; 

App.jsx(符号省略多くの)

//他のすべてのコードは

const playerData = { 
    name, 
    score: this.state.totalScore, 
    }; 

    client.createPlayer(playerData, 
    (err) => { 
     // TODO: improve error message 
     console.log(err); 
    }, 
    client.getPlayers((data) => { 
     // array of objects containing all but most recent entry 
     console.log(data); 
     this.setState({ 
     inputScreen: false, // hide the input screen 
     highScoreScreen: true, // show the high score screen 
     yeti: yetiWin, 
     highScores: [...this.state.highScores, ...data], 
     }); 
    }, (err) => { 
     // TODO: improve this error message 
     console.log(err); 
    }) 
); 
を省略

//他のすべてのコードは省略されています

データ変数には新しく作成されたプレーヤーは含まれませんが、他のプレーヤーは含まれません。したがって、作成および読み取り操作はサーバー側で行われています。私は以下のようなものに自分のApp.jsxを変更する場合:

App.jsx(トライアル)

const playerData = { 
    name, 
    score: this.state.totalScore, 
    }; 

    client.createPlayer(playerData, 
    (err) => { 
     // TODO: improve error message 
     console.log(err); 
    }, 
    (res) => { 
     // should contain something like: 
     // { 
     //  "__v": 0, 
     //  "_id": "5881922f441fda40ccc52f83", 
     //  "name": "player name", 
     //  "score": "123" 
     // } 
     // right? 
     console.log(res.json()); 
     console.log(res); 
     console.log(res.body); 
    } 
); 

私が手に私はres.jsonresres.bodyをログ:

約束{[[PromiseStatus ]]:[保留]、[[PromiseValue]]:未定義}

回答{type: "basic"、url: "http://localhost:3000/api/players」、状況:200、[OK]:真、STATUSTEXT: "OK" ...}

ReadableStream {}

私は郵便配達で、私のPOSTエンドポイント(http://localhost:3001/api/players)をテストする場合、サーバーが含むJSONオブジェクトで応答私が望むデータ何らかの理由でclient.createPlayerはサーバーからデータを返しません。もちろん、それは問題のほんの一部です。理論的には

、私のclient.createPlayer解決し、私はこの方法が正しい、私は新たに作成された選手を含めたいデータを返す必要がありclient.createPlayerへのコールバックとしてclient.getPlayersを呼び出したら?

ただし、そうではないようです。

私は間違っていますか?

+0

この 'http:// localhost:3001'は疑わしいと思われます。私はそれを' http:// localhost:3001'とすると、要求を出しているページがどこからロードされているのでしょうか? 'http:// localhost:80'か何か - フェッチのあなたのURLが' '/ api/players''であることがわかります、それは実際のコードです。あなたは質問だけを削除していません。 「クロスオリジン」リクエストですか? –

+0

@ JaromandaX create-react-appを使用しているので、クライアントサーバーはlocalhost:3000で実行され、エクスプレスサーバーはlocalhost:3001で実行されています。クライアントは、localhost:3001へのプロキシ要求をセットアップします。 –

+0

ok - CORSの問題ではないことを確認するだけです –

答えて

1

興味深いことに、App.jsxのコードを次のように変更すると、私は後に結果を出すことができました。しかし、私はこの変更がなぜ機能するのか完全に理解していないので、私は正しい解決策として私の答えを記してはいません。

誰かがチャイムインして、なぜ今これが機能するのか説明したいのであれば、その理由を聞くのが大好きです。

App.jsx(固定)

// all other code omitted 

    client.createPlayer(playerData, (err) => { 
    console.error(err); 
    }, (data) => { 
    this.setState({ 
     highScores: [...this.state.highScores, ...data], 
    }); 
    });  

    client.getPlayers((data) => { 
    this.setState({ 
     inputScreen: false, // hide the input screen 
     highScoreScreen: true, // show the high score screen 
     yeti: yetiWin, 
     highScores: [...this.state.highScores, ...data], 
    }); 
    }, (err) => { 
    console.error(err); 
    }); 

// all other code omitted 

あなたは、私はもはやclient.createPlayerに成功コールバックとしてclient.getPlayersを起動していないことに注意しましょう。その上で私はclient.createPlayerから返されたデータを使用して、client.createPlayerメソッドがclient.getPlayersメソッドの前に終了しない場合のフォールバックとして状態に追加しています。これにより、setStateが再レンダリングを発行すると、新しいプレーヤーが確実に表示されます。

関連する問題