如何使用异步?
How to use async?
我正在做一个 for 循环来检查一些值,这里是一个简短的版本。我不明白的是为什么 console.log(indirizzo[a]);
给出 undefined 而如果我这样做 console.log(indirizzo);
我得到所有值
var indirizzo = [];
for (var i = 0; i < savedRepods.length; i++) {
for (var a = 0; a < ids.length; a++) {
if(savedRepods[i] == ids[a]) {
var geocoder = new google.maps.Geocoder;
var latlngStr = coords[a].split(',', 2);
var latlng = {lat: parseFloat(latlngStr[0]), lng: parseFloat(latlngStr[1])};
geocoder.geocode({'location': latlng}, function(results, status) {
indirizzo.push(results[0].formatted_address);
});
console.log(indirizzo[a]);
}
}
}
我这样做的结果console.log(indirizzo);
0: "Corso Vittorio Emanuele, 1, 09017 Sant'Antioco SU, Italia"
1: "Via Nazionale, 78, 09017 Sant'Antioco SU, Italia"
2: "Via Giosuè Carducci, 15, 09017 Sant'Antioco SU, Italia"
3: "Via Perret, 11, 09017 Sant'Antioco SU, Italia"
4: "Lungomare Amerigo Vespucci, 2A, 09017 Sant'Antioco SU, Italia"
我这样做的结果console.log(indirizzo[a]);
undefined
我知道地理编码器与 per the docs 一样是异步的,但我对在我的案例中将回调放在何处感到很困惑。
来自 [Mark Meyer][1] 回复:
您的主要问题是 geocoder.geocode()
是异步的并且需要回调。您正在将一个函数传递给回调,但将 return 值视为它将 return 来自主函数 findLatLang()
,但它不会。目前 findLatLang()
return 什么都没有。
findLatLang()
是你应该得到承诺的地方,return 它来自函数:
function findLatLang(address, geocoder, mainMap) {
return new Promise(function(resolve, reject) {
geocoder.geocode({'location': address}, function(results, status) {
if (status === 'OK') {
console.log(results);
resolve([results[0].geometry.location.lat(), results[0].geometry.location.lng()]);
} else {
reject(new Error('Couldnt\'t find the location ' + address));
}
})
})
}
然后在 getPoints()
的循环中,您可以将这些承诺收集到一个数组中,然后在数组上调用 Promise.all()
,一旦所有承诺都已解决,该数组将为您提供值:
function getPoints(geocoder,map) {
let locationData = [];
var indirizzo = [];
for (var i = 0; i < savedRepods.length; i++) {
for (var a = 0; a < ids.length; a++) {
if(savedRepods[i] == ids[a]) {
var geocoder = new google.maps.Geocoder;
var latlngStr = coords[a].split(',', 2);
var latlng = {lat: parseFloat(latlngStr[0]), lng: parseFloat(latlngStr[1])};
locationData.push(findLatLang(latlng, geocoder, map))
console.log(indirizzo[a]);
}
}
}
return locationData // array of promises
}
var locations = getPoints(geocoder,map)
Promise.all(locations)
.then(function(returnVals){
// you should have return values here when
// all promises have rsolved
console.log(returnVals);
})
Promise.all()
方法 return 是一个单一的 Promise,当所有作为可迭代对象传递的 promises 都已实现或当 iterable 不包含任何 promises 或当 iterable 包含已被传递的 promises 时,它会实现returned.
已兑现和未兑现的承诺
不清楚 addressData
的来源 - 您在函数中使用它,但它没有被传递到任何地方。
查看 [Mark Meyer][1] 的概念证明:
代码片段:
(function($) {
var savedRepods = <?php echo json_encode($userPostsInternal); ?>;
savedRepods = savedRepods.split(",");
var date = [],
coords = [],
ids = [],
metal = [],
plastic = [],
paper = [],
glass = [],
indirizzo = [];
var array = <?php echo $contents; ?>;
array.map(function(item) {
coords.push(item.Lat + "," + item.Lng);
ids.push(item.ID);
date.push(item.Date);
plastic.push(item.Plastic);
paper.push(item.Paper);
glass.push(item.Glass);
metal.push(item.Metal);
});
/**
* findLatLang
*/
function findLatLang(location, geocoder, value) {
/**
* Return new Promise what resolves when
* the geocoder is successfull
* and push in the array of promises
*/
return new Promise(function(resolve, reject) {
/** Do geocoder */
geocoder.geocode({
'location': location
}, function(results, status) {
/**
* If geocoder is Ok
*/
if (status === 'OK') {
/**
* When the geocoder is successfull located
* resolve the promise and send the response of formate address
*/
resolve([results[0].formatted_address, value]);
} else {
/**
* Reject the promise
*/
reject(new Error('Couldnt\'t find the location ' + location));
}
})
})
}
/**
* processData
* return an array of promises
*/
function getPoints() {
/**
* Declare a variable of promises that have a geocoder
*/
let locationData = [];
for (var i = 0; i < savedRepods.length; i++) {
for (var a = 0; a < ids.length; a++) {
if (savedRepods[i] == ids[a]) {
var geocoder = new google.maps.Geocoder;
var latlngStr = coords[a].split(',', 2);
var latlng = {
lat: parseFloat(latlngStr[0]),
lng: parseFloat(latlngStr[1])
};
/**
* Push geocoder in array of locationdata
* Send the geocoder object on function and send the map
*/
locationData.push(findLatLang(latlng, geocoder, a))
}
}
}
/** return array of promises */
return locationData;
}
/**
* Now process the response from locationData
*/
var locations = getPoints();
/**
* Promise all
* freecodecamp.org/news/…
* The Promise.all() method returns a single Promise that fulfills when all of the promises
* passed as an iterable have been fulfilled or when the iterable contains no promises or when
* the iterable contains promises that have been fulfilled and non-promises that have been returned.
* It rejects with the reason of the first promise that rejects, or with the error caught by the
* first argument if that argument has caught an error inside it using try/catch/throw blocks.
* ONLY RETURN VALUE WHEN ALL PROMISES HAS ENDED
* @TODO => SHOW LOADER IN PROCESS
*/
Promise.all(locations)
.then(function(returnVals) {
console.warn(returnVals)
_indirizzo = returnVals;
doAddress(_indirizzo)
});
function doAddress(_indirizzo) {
_indirizzo.forEach(function(item) {
var a = item[1];
var location = item[0];
$("#eachValue ul").append("<li class='list-group-item'>repod id= " + ids[a] + "<br> Indirizzo = " + location + "<br> Metallo = " + metal[a] + ", <br> Plastica = " + plastic[a] + ", <br> Vetro = " + glass[a] + ", <br> Carta = " + paper[a] + "</li>");
})
}
})(jQuery);
我正在做一个 for 循环来检查一些值,这里是一个简短的版本。我不明白的是为什么 console.log(indirizzo[a]);
给出 undefined 而如果我这样做 console.log(indirizzo);
我得到所有值
var indirizzo = [];
for (var i = 0; i < savedRepods.length; i++) {
for (var a = 0; a < ids.length; a++) {
if(savedRepods[i] == ids[a]) {
var geocoder = new google.maps.Geocoder;
var latlngStr = coords[a].split(',', 2);
var latlng = {lat: parseFloat(latlngStr[0]), lng: parseFloat(latlngStr[1])};
geocoder.geocode({'location': latlng}, function(results, status) {
indirizzo.push(results[0].formatted_address);
});
console.log(indirizzo[a]);
}
}
}
我这样做的结果console.log(indirizzo);
0: "Corso Vittorio Emanuele, 1, 09017 Sant'Antioco SU, Italia"
1: "Via Nazionale, 78, 09017 Sant'Antioco SU, Italia"
2: "Via Giosuè Carducci, 15, 09017 Sant'Antioco SU, Italia"
3: "Via Perret, 11, 09017 Sant'Antioco SU, Italia"
4: "Lungomare Amerigo Vespucci, 2A, 09017 Sant'Antioco SU, Italia"
我这样做的结果console.log(indirizzo[a]);
undefined
我知道地理编码器与 per the docs 一样是异步的,但我对在我的案例中将回调放在何处感到很困惑。
来自 [Mark Meyer][1] 回复:
您的主要问题是 geocoder.geocode()
是异步的并且需要回调。您正在将一个函数传递给回调,但将 return 值视为它将 return 来自主函数 findLatLang()
,但它不会。目前 findLatLang()
return 什么都没有。
findLatLang()
是你应该得到承诺的地方,return 它来自函数:
function findLatLang(address, geocoder, mainMap) {
return new Promise(function(resolve, reject) {
geocoder.geocode({'location': address}, function(results, status) {
if (status === 'OK') {
console.log(results);
resolve([results[0].geometry.location.lat(), results[0].geometry.location.lng()]);
} else {
reject(new Error('Couldnt\'t find the location ' + address));
}
})
})
}
然后在 getPoints()
的循环中,您可以将这些承诺收集到一个数组中,然后在数组上调用 Promise.all()
,一旦所有承诺都已解决,该数组将为您提供值:
function getPoints(geocoder,map) {
let locationData = [];
var indirizzo = [];
for (var i = 0; i < savedRepods.length; i++) {
for (var a = 0; a < ids.length; a++) {
if(savedRepods[i] == ids[a]) {
var geocoder = new google.maps.Geocoder;
var latlngStr = coords[a].split(',', 2);
var latlng = {lat: parseFloat(latlngStr[0]), lng: parseFloat(latlngStr[1])};
locationData.push(findLatLang(latlng, geocoder, map))
console.log(indirizzo[a]);
}
}
}
return locationData // array of promises
}
var locations = getPoints(geocoder,map)
Promise.all(locations)
.then(function(returnVals){
// you should have return values here when
// all promises have rsolved
console.log(returnVals);
})
Promise.all()
方法 return 是一个单一的 Promise,当所有作为可迭代对象传递的 promises 都已实现或当 iterable 不包含任何 promises 或当 iterable 包含已被传递的 promises 时,它会实现returned.
不清楚 addressData
的来源 - 您在函数中使用它,但它没有被传递到任何地方。
查看 [Mark Meyer][1] 的概念证明:
代码片段:
(function($) {
var savedRepods = <?php echo json_encode($userPostsInternal); ?>;
savedRepods = savedRepods.split(",");
var date = [],
coords = [],
ids = [],
metal = [],
plastic = [],
paper = [],
glass = [],
indirizzo = [];
var array = <?php echo $contents; ?>;
array.map(function(item) {
coords.push(item.Lat + "," + item.Lng);
ids.push(item.ID);
date.push(item.Date);
plastic.push(item.Plastic);
paper.push(item.Paper);
glass.push(item.Glass);
metal.push(item.Metal);
});
/**
* findLatLang
*/
function findLatLang(location, geocoder, value) {
/**
* Return new Promise what resolves when
* the geocoder is successfull
* and push in the array of promises
*/
return new Promise(function(resolve, reject) {
/** Do geocoder */
geocoder.geocode({
'location': location
}, function(results, status) {
/**
* If geocoder is Ok
*/
if (status === 'OK') {
/**
* When the geocoder is successfull located
* resolve the promise and send the response of formate address
*/
resolve([results[0].formatted_address, value]);
} else {
/**
* Reject the promise
*/
reject(new Error('Couldnt\'t find the location ' + location));
}
})
})
}
/**
* processData
* return an array of promises
*/
function getPoints() {
/**
* Declare a variable of promises that have a geocoder
*/
let locationData = [];
for (var i = 0; i < savedRepods.length; i++) {
for (var a = 0; a < ids.length; a++) {
if (savedRepods[i] == ids[a]) {
var geocoder = new google.maps.Geocoder;
var latlngStr = coords[a].split(',', 2);
var latlng = {
lat: parseFloat(latlngStr[0]),
lng: parseFloat(latlngStr[1])
};
/**
* Push geocoder in array of locationdata
* Send the geocoder object on function and send the map
*/
locationData.push(findLatLang(latlng, geocoder, a))
}
}
}
/** return array of promises */
return locationData;
}
/**
* Now process the response from locationData
*/
var locations = getPoints();
/**
* Promise all
* freecodecamp.org/news/…
* The Promise.all() method returns a single Promise that fulfills when all of the promises
* passed as an iterable have been fulfilled or when the iterable contains no promises or when
* the iterable contains promises that have been fulfilled and non-promises that have been returned.
* It rejects with the reason of the first promise that rejects, or with the error caught by the
* first argument if that argument has caught an error inside it using try/catch/throw blocks.
* ONLY RETURN VALUE WHEN ALL PROMISES HAS ENDED
* @TODO => SHOW LOADER IN PROCESS
*/
Promise.all(locations)
.then(function(returnVals) {
console.warn(returnVals)
_indirizzo = returnVals;
doAddress(_indirizzo)
});
function doAddress(_indirizzo) {
_indirizzo.forEach(function(item) {
var a = item[1];
var location = item[0];
$("#eachValue ul").append("<li class='list-group-item'>repod id= " + ids[a] + "<br> Indirizzo = " + location + "<br> Metallo = " + metal[a] + ", <br> Plastica = " + plastic[a] + ", <br> Vetro = " + glass[a] + ", <br> Carta = " + paper[a] + "</li>");
})
}
})(jQuery);