Я использую Geocodio, это геокодирование на основе обратного вызова. У меня есть массив объектов, каждый из которых имеет объект ресторана, вложенный в него. См. Пример ниже:
{
id: 0, title: "Half off all pizzas",
details:"Carry out only, all-day",
days: ["Monday", "Tuesday"],
restaurant: {
name: "Papa John's",
addressOne: "2937 Greenville Ave",
city: "Dallas",
state: "TX",
zip: 75206
}
}
В настоящее время я просматриваю массив объектов, чтобы передать каждый адрес ресторана в функцию геокодирования. Затем я хочу добавить свойство к этому объекту, называемому местоположением, которое будет содержать результаты геокодирования. Однако элемент возвращается до того, как результаты функции могут быть переданы в объект. Увидеть ниже:
generateCoordinates (req, res, next) {
var newDeals = deals.map((cur, ind, arr) => {
location = new Promise (function(resolve, reject) {
geocodio.get('geocode', {q: '${cur.restaurant.addressOne},
${cur.restaurant.city}, ${cur.restaurant.state},
${cur.restaurant.zip}'}, function(err, response) {
if (err) {
reject(err)
throw err;
}
else {
var result = JSON.parse(response);
let obj = result.results[0].location;
// console.log(obj);
resolve(obj)
}
}
)}).then((obj) => {
cur.location = obj;
console.log(cur)
return cur;
})
return cur;
// console.log(newDeals)
})
res.status(200).send(newDeals)
},
Там хороший шанс, что я злоупотребляю конструктором Promise здесь. Консоль.log в.then показывает, что каждый элемент имеет правильное добавление свойства местоположения, но ответ и console.log(newDeals) показывают значение как "Promise".
Как установить свойство location для каждого элемента массива?
Да, вы не должны ничего делать в обратном вызове async, но для вызова resolve
или reject
. Особенно вы не должны throw
!
return cur
не работает точно, потому что это происходит до того, как обещание будет разрешено. Вам нужно будет вернуть обещание из обратного вызова map
а затем дождаться всех обещаний в массиве, используя Promise.all
. Когда это будет наконец выполнено, только тогда вы сможете отправить ответ. Также не забудьте отправить соответствующий ответ при возникновении ошибки.
generateCoordinates (req, res, next) {
var newDeals = deals.map((cur, ind, arr) =>
new Promise((resolve, reject) => {
geocodio.get('geocode', {
q: '${cur.restaurant.addressOne},
${cur.restaurant.city}, ${cur.restaurant.state},
${cur.restaurant.zip}'
}, (err, response) => {
if (err) reject(err);
else resolve(response);
});
}).then(response => {
var result = JSON.parse(response);
let obj = result.results[0].location;
cur.location = obj;
console.log(cur)
return cur;
})
);
Promise.all(newDeals).then(results => {
res.status(200).send(results);
}, err => {
res.status(500); // or whatever
console.error(err);
});
}
undefined
Итак, вы хотите вернуть массив значений? у вас почти есть это, но вам нужно ждать, пока обещания разрешатся. что-то вроде этого:
generateCoordinates (req, res, next) {
var newDeals = deals.map((cur, ind, arr) => {
return new Promise (function(resolve, reject) {
geocodio.get('geocode', {q: '${cur.restaurant.addressOne},
${cur.restaurant.city}, ${cur.restaurant.state},
${cur.restaurant.zip}'}, function(err, response) {
if (err) {
return reject(err);
}
else {
var result = JSON.parse(response);
let obj = result.results[0].location;
// console.log(obj);
resolve(obj)
}
}
)}).then((obj) => {
cur.location = obj;
console.log(cur)
return cur;
});
//newDeals is an array of promises at this point
Promise.all(newDeals).then(results => {
//results here is a value resolved from your promise above
return res.status(200).send(results)
}).catch(er r=> {
//handle errror
});
},
То, что я делаю, это использовать карту здесь, чтобы создать массив обещаний. Затем используйте Promise.all
чтобы дождаться обещаний. все, что вы вернетесь из then
блокировать внутри вашей map
будет в конечном итоге, как массив в then
блок Promise.all
. Если вы Promise.all
от каких-либо обещаний, они автоматически поймают их в Promise.all
Promise.all
для возвращаемого массива.geocodio.get()
лиgeocodio.get()
Promise
? Вы могли бы избежать явной конструкции Promise, если она это сделает.