Ожидайте небольшой API, который задерживает запросов к API использования async/с Node.js


Я потратил несколько часов поиск и устранение неисправностей ошибка, когда брешут-фьюжн API сказали, что я посылаю слишком много запросов в секунду, так что я, наконец, нашел способ задерживать каждый запрос API, чтобы заставить его работать. Пожалуйста, взгляните на код и дайте мне любые советы у вас есть. Я бы хотел увидеть, как это может быть сделано в лучшую сторону, если это возможно.

Вот мой server.js где размещать запросы приходят через:

  //handle post requests for getting yelp data
  app.post('/post', async function(req, res) {
    let yelpInData = []
    let result = null;
    req.body.forEach((item) => {
      yelpInData.push(item);
    });

    result = await handleYelp(yelpInData);
    //send data back to the front end
    res.send(result);

  });

  //handle yelp api
  async function handleYelp(yelpInData) {
    let yelpData = [];

    for (let i = 0, len = yelpInData.length; i < len; i++) {
      let result = await searchPlace(yelpInData[i]);
      yelpData.push(result);
    }
    //  console.log(yelpData);
    return yelpData;

  }

  function searchPlace(city) {
    //console.log(city)
    return new Promise((resolve) => {
      setTimeout(() => {
        let coords = city.coords.lat + "," + city.coords.lng;
        let name = city.name;

        client.search({term: name, location: coords}).then(response => {

          //name, img url, review count, rating, price, location.display address, is closed,phone
          resolve({
            name: response.jsonBody.businesses[0].name,
            img: response.jsonBody.businesses[0].image_url,
            hours: response.jsonBody.businesses[0].is_closed,
            revcount: response.jsonBody.businesses[0].review_count,
            rating: response.jsonBody.businesses[0].rating,
            price: response.jsonBody.businesses[0].price,
            location: response.jsonBody.businesses[0].location.display_address.toString(),
            phone: response.jsonBody.businesses[0].display_phone,
            url: response.jsonBody.businesses[0].url
          });

        }).catch(e => {
          console.log(e);
        });
      }, 100);
    })
  }

Метод setTimeout является хорошей идеей для затягивания запросов к API в суд или есть другой способ задержки? Вот в Git РЕПО, если вы хотите запустить веб-приложение: https://github.com/capozzic1/knockout_map



490
0
задан 13 февраля 2018 в 06:02 Источник Поделиться
Комментарии
2 ответа

setTimeout за задержку так же хорошо, как любой другой подход, если вы счастливы, чтобы держать нагрузку на сервер. Другой вариант заключается в разделении обработки от планирования например, разгрузить эти конкретные просьбы к службе планирования, а затем капельно кормить их обратно в ваше приложение для обработки.

С точки зрения кода, есть несколько небольших вещей, которые вы можете сделать, чтобы прибраться там немного.... но самой большой проблемой я вижу с вашего кода в данный момент нет абсолютно нулевой обработки ошибок. Экспресс имеет обработчик ошибок по умолчанию, которая удобно ловит ошибки внутри промежуточного слоя, однако, просто будьте осторожны, что вы рискуете из-за утечки внутренних данных сервера клиенту, если вы позволите вы просто оставляете свои ошибки, чтобы пузыриться.

Здесь немного порядок обработки и ошибок

// handle post requests for getting yelp data
app.post('/post', async (req, res, next) => {
try {
// nice use of map makes handleYelp redundant :)
const searches = req.body.map(x => searchPlace(x));
const results = await Promise.all(searches);
return res.send(results);
} catch (e) {
console.error(e); // log internal error
return next(new Error('Internal Server Error')); // return public error to client
}
});

function searchPlace(city) {
return new Promise((resolve, reject) => {
// use async / await here too :)
setTimeout(async () => {
try {
const name = city.name;
const location = `${city.coords.lat},${city.coords.lng}`;
const result = await client.search({ name, location });
const business = result.jsonBody.businesses[0];
resolve({
name: business.name,
img: business.image_url,
hours: business.is_closed,
revcount: business.review_count,
rating: business.rating,
price: business.price,
location: business.location.display_address.toString(),
phone: business.display_phone,
url: business.url
});
} catch (e) {
return reject(e);
}
}, 100);
})
}

1
ответ дан 13 февраля 2018 в 12:02 Источник Поделиться

Не знаю, зачем нужен новый массив на DAT, вы не мутирует массива. Единственная причина, я бы мелкой-клон, если что-то еще мутирует массива (и это должно быть исправлено). Если у вас нет пути вокруг него, более короткий путь к мелкой-клон массива распространяться через оператора, или по-старинке array.slice(0).

Также, вы можете аннотация таймер как ожидать. Возвращать обещание и await он внутри async функция.

Петли очень boilerplatey, потому что это очень важно. Альтернативным способом будет использование рекурсии.

Если вы конкатенации строк, я рекомендую использовать шаблон литералы. JavaScript может получить действительно обалденный, когда concating переменных с +. Это обычно зависит от того, что первая переменная. Если это строка, то она concats как струна. Но если это число случайно, это будет математика, и вы получите NaN.

Вы также можете использовать свойства объекта стенографии, чтобы сократить назначение пар ключ-значение. Как долго, как имя переменной совпадает со значением свойства имя, вы можете пропустить задание часть (в : value часть объекта) и просто назначить клавишу.

Вот код, который может работать с учетом корректировок выше.

const sleep = delay => new Promise(resolve => { setTimeout(resolve, delay) }, delay)

app.post('/post', async function (req, res) {
try {
res.send(await search([...req.body]))
} catch (e){
// Handle the failure
}
});

async function search(data) {
// No more data.
if(!data.length) return []

// Get the next city in line and do a request for it.
const city = data[0]
const term = city.name
const location = `${city.coords.lat},${city.coords.lng}`
const response = await client.search({ term, location })

// Build the data
const business = response.jsonBody.businesses[0]
const result = {
name: business.name,
img: business.image_url,
hours: business.is_closed,
revcount: business.review_count,
rating: business.rating,
price: business.price,
location: business.location.display_address.toString(),
phone: business.display_phone,
url: business.url
}

// Wait for the sleep promise to resolve
await sleep(1000)

// Return an array with the result of the current city plus the results of the rest.
return [result, ...(await search(data.slice(1)))]
}

1
ответ дан 13 февраля 2018 в 02:02 Источник Поделиться