发出$http请求会以几种不同的方式返回undefined



我刚开始使用Node.js,我正试图用pokeAPI制作一个pokedex,我在使用$q和$http请求时遇到了问题。当我尝试进行api调用时,它会返回"ReferenceError:getPokes未定义"。在试图找出原因时,我发现将getPokes放在变量上会导致错误转到"ReferenceError:response is not defined"。也许我不需要它,我误解了逻辑。不管怎样,我知道我遗漏了一些重要的逻辑,也许是我的控制器里有什么?我们非常感谢您的帮助!

编辑:我后来发现,如果我从中删除pokeName。willCollectThemAll,它会带回请求中pokeName所在的$http请求,并显示未定义(http://pokeapi.co/api/v2/pokemon/+pokeName。这是有道理的,因为它没有被传递,但它显示$http正在完成,不像我把pokeName放进这个.willCollectThemAll的地方,它说函数getPokes是未定义的,这就是我被难住的地方。

服务:

// INITIALIZE SERVICE
// ============================================================
angular.module("app").service("pokeService", function($http, $q, $timeout) {
// ============================================================
this.willCollectThemAll = function(pokeName) {
var deferred = $q.defer();
var pokemon = false;
var morePokemon = false;
var pokemonCaught = false;
var allPokemonCaught = false;

getPokes = function(pokeName) {
$http({
url: 'http://pokeapi.co/api/v2/pokemon/' + pokeName,
method: 'GET'
}).then(function(response) {
console.log('service:', response);
pokemon = response.data;
pokemonCaught = True;
checkAllPokemon();
})
}
getMorePokes = function(pokeName) {
$http({
url: 'http://pokeapi.co/api/v2/pokemon-species/' + pokeName,
method: 'GET'
}).then(function(response) {
console.log('service:', response);
morePokemon = response.data;
allPokemonCaught = true;
checkAllPokemon();
})
}
function checkAllPokemon() {
if (pokemonCaught && allPokemonCaught) {
if (pokemon && morePokemon) {
deferred.resolve(true);
} else {
deferred.reject(true)
}
}
}
console.log('service', response)
getPokes();
getMorePokes();
return deferred.promise;
}

});

控制器:

// INITILIZE CONTROLLER
// ============================================================
angular.module("app").controller("pokeCtrl", function($scope, $q, pokeService) {
// VARIABLES
// ============================================================

// FUNCTIONS
// ============================================================
$scope.willCollectThemAll = function() {
pokeService.willCollectThemAll($scope.pokeName.toLowerCase())
.then(function(response) {
console.log(pokeService, response);
$scope.pokeData = response;
})
}

});

我可以看到您的代码有几个问题,第一个问题是您必须返回丢失的$http调用。在您的服务中尝试以下操作

this.willCollectThemAll = function(pokeName) {
var deferred = $q.defer();
var pokemon = false;
var morePokemon = false;
var pokemonCaught = false;
var allPokemonCaught = false;

getPokes = function(pokeName) {
return $http({
url: 'http://pokeapi.co/api/v2/pokemon/' + pokeName,
method: 'GET'
}).then(function(response) {
return response.data;
})
}
getMorePokes = function(pokeName) {
return $http({
url: 'http://pokeapi.co/api/v2/pokemon-species/' + pokeName,
method: 'GET'
}).then(function(response) {
return response.data;
})
}
function checkAllPokemon() {
if (pokemonCaught && allPokemonCaught) {
if (pokemon && morePokemon) {
deferred.resolve(true);
} else {
deferred.reject(true)
}
}
}
getPokes().then(function (data){
pokemon = data;
pokemonCaught = true;
checkAllPokemon();
});
getMorePokes().then(function (data){
morePokemon = response.data;
allPokemonCaught = true;
checkAllPokemon();
});
return deferred.promise;
}

这个东西看起来像是与Charizard发生了冲突。

我再次认为@AliBaig有权这样做,但应用程序逻辑本身是错误的。我认为你是想把承诺连锁起来,这样如果你第一次没有得到更多的口袋妖怪。

这是对你的代码的快速检查。

this.willCollectThemAll = function(pokeName) {
// $q.when() is a nice shortcut for this logic and creates a new promise each time.
//var deferred = $q.defer();
var pokemon;  // prolly better to make these empty arrays then check for length instead of checking for boolean value.
var morePokemon;
var pokemonCaught = false;
var allPokemonCaught = false;
// getPokes returns a promise.
var getPokes = function(pokeName) {
return $http({
url: 'http://pokeapi.co/api/v2/pokemon/' + pokeName,
method: 'GET'
}).then(function(response) {
return response.data;
})
}
// getMorePokes also returns a promise.
var getMorePokes = function(pokeName) {
return $http({
url: 'http://pokeapi.co/api/v2/pokemon-species/' + pokeName,
method: 'GET'
}).then(function(response) {
return response.data;
})
}
// If you resolve the promise here you will be trying to resolve the same promise multiple times.
function checkAllPokemon() {
if (pokemonCaught && allPokemonCaught) {
if (pokemon && morePokemon) {
//deferred.resolve(true);
return true;
} else {
//deferred.reject(true);
return false;
}
}
}
// Have getPokes() return a promise and give this promis back to the controller.
return getPokes().then(function (data){
pokemon = data;
pokemonCaught = true;
// In either case here we're gonna return a promise.
if ( !checkAllPokemon() ) {
return getMorePokes().then(function(data) {
morePokemon = response.data;
allPokemonCaught = true;
//returning pokemon with ES6 syntax cuz I'm lazy.
return checkAllPokemon() ? $q.when([...pokeman, ...morePokemon]) : $q.reject('Did not getem all. :(');
});
} else {
// If we already have the pokemon don't bother chaining again.
return $q.when([...pokeman, ...morePokemon]);
}
});
}

请注意,应该正确考虑大量错误路径。

最新更新