Async Javascript: Пытаетесь делать вызовы AJAX API несколько раз с интервалом? - PullRequest
0 голосов
/ 07 октября 2018

Итак, у меня есть форма, пользователь ищет запрос.

Попытка сделать:

Я последовательно выполняю вызовы API.Первый запрос вводится пользователем, затем программа создает новые запросы на основе Entity Analysis и выполняет вызовы API самостоятельно - снова и снова.

Проблема: результаты совпадают, что означает кодвыполняет вызовы API на основе начального запроса снова и снова вместо создания новых запросов из результатов API.

Результат в консоли:

queries length is zero...
Iterating...  undefined
On Queue Searches #1:  []
query length is zero
POST / 200 15.747 ms - -
 etc. etc. etc.

code

Отправка запроса, введенного пользователем, в массив, отправка его на onQueueSearch для выполнения вызовов API с заданным интервалом.

// Global Queries
const queries = new Array();
let counter = 0; // Just to keep track

    router.post('/', async (req, res) => {
        // Assign first query
        queries.push(req.body.searchTerm);
        // Invoke the async iterator
        const results = await queryIterator(queries);
        res.send(results);
       });

Эта функция может быть проблемой? Для каждого запроса в массиве передавать его в sentimentAnalyze, который вызывает API-интерфейсы. Предполагается, что эта функция должна последовательно выполнять вызовы API-интерфейса при установке.интервал. (Примечание. Новые запросы добавляются в массив запросов в вызовах API.)

async function onQueueSearch() {

      if(queries.length === 0 ) {
        console.log("queries length is zero...");
        return; // return something if empty
      }
      // This will extract the next in queue and remove it from queries    
      return await sentimentAnalyze(queries.pop); 
  }

// Define functions for Async Iterator -----
async function* queryGenerator() {
  while (true) {
      yield await onQueueSearch(queries.pop());
  }
}

async function queryIterator(queries) {
  for await (const result of queryGenerator()) {
      console.log('Iterating... ', result);
      console.log(`On Queue Searches #${++counter}: `, queries);
      if (!queries.length) {
          console.log("query length is zero");
          return result;
      }
  }
}

Функция вызовов API - возвращает набор результатов Twitter, а затем GoogleРезультаты API - эта асинхронная функция пытается дождаться возвращенных обещаний / результатов из твиттера Google API и возвращает

async function sentimentAnalyze(searchValue) {
  try {
     const tweetDocumentObject = await searchTwitter(searchValue);
     const sentimentResults = await googleSentimentAnalyze(tweetDocumentObject); 
     const entitiesResults = await googleEntityAnalyze(tweetDocumentObject);
     return {sentimentResults, entitiesResults};
 } catch(err) {
     console.log('sentimentAnalyze Error: ', err);
 }   
}

Эта функция, где новые запросы добавляются из анализа сущностей.

   function googleEntityAnalyze(document) {
  return new Promise((resolve, reject) => {
    // Detects entities in the document
    googleClient
    .analyzeEntities({document: document})
    .then(results => {
      const entities = results[0].entities;

      queries.unshift(req.body.searchTerm);
      entities.forEach(entity => {
          queries.unshift(entity.name);
            // console.log("Entitiy name: " +entity.name);
        // console.log(` - Type: ${entity.type} `);
        resolve({ entity  });
      });
    })
    .catch(err => {
      console.error('ENTITY ERROR:', err);
    });

  });
}

1 Ответ

0 голосов
/ 08 октября 2018

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

Первое из:

Вы всегда толкаете в очередь, это основная причина того, что вы получаете одни и те же данные в очереди:

queries.push(req.body.searchTerm); // searchTerm being '1'
... // Do more logic until googleEntityAnalyze
  entities.forEach(entity => {
    queries.push(entity.name);
    resolve({ entity  });
  });
 // Assume entities as [2, 3]

Теперь у вас есть очередь как [1,2,3],будучи 1 в качестве первого аргумента.Затем вы возвращаете логику запроса из:

async function onQueueSearch() {

  for(i = 0; i < queries.length; i++) {
    return await sentimentAnalyze(queries[i]);
     // queries[i].splice(i, 1);
  } 

  if(queries.length === 0 ) {
    console.log("queries length is zero...");
  }

}

Возвращение цикла for прервет цикл и вернет первое выполнение, которое будет queries[0] === 1, вашим первым аргументом.

Поэтому, чтобы решить эту проблему, сохраняйте массив в порядке поступления, используя:

queries.unshift(req.body.searchTerm);
entities.forEach(entity => {
    queries.unshift(entity.name);
    resolve({ entity  });
});

Это будет поддерживать ваши запросы в порядке их поступления [3,2,1] вместо [1,2,3], теперь вы можете извлечь ваш запрос, используя queries.pop().

queries.unshift(4); // where queries was [3,2,1], will be [4,3,2,1]
queries.pop(); // 1

Измените анализ настроений на:

 async function onQueueSearch(){

      if(queries.length === 0 ) {
        console.log("queries length is zero...");
        return; // Return something if empty!
      }
      return await sentimentAnalyze(queries.pop());
      // This will extract the next in queue and remove it from queries    
  }

Во-вторых, ваша логика повторного вызова

Youпри использовании iterval для непрерывного вызова запроса, проблема в следующем:

setInterval(async function() { 
    results = await onQueueSearch(); 
  }, 3000);

Требуется ли «оценка» времени, которое потребуется для выполнения запроса до повторного запроса?выполнения.С помощью запроса unshift и всплывающего окна вы справитесь с этой задачей, однако вам нужно более элегантное решение.

С версией NodeJS <10 +: </strong>

рекурсия будетполезно, вот небольшой пример того, что вы делаете простым способом:

const queries = [1];
let counter = 0; // Just to keep track
async function reRunQueries(){
    counter++;
    console.log(`queries #${counter}: `, queries);
    results = await onQueueSearch();
    console.log('Results: ', results);
    if(!!queries.length){
        return await reRunQueries();
    }else{
        return results;
    }
}

async function onQueueSearch(){
    return await longQuery(queries.pop()); 
}

async function longQuery(param){
   if(param === 6){
       // Use this as stop signal!
       return param;
   }else{
       queries.unshift(++param);
       return param;
   }
}

const RES = reRunQueries();
RES.then(result => {
    console.log('RES: ', result);
})

Важно знать ваш сигнал остановки для рекурсии, иначе он никогда не закончится.

с NodeJS> 10 +

Использовать многократный генератор:

const queries = [];
let counter = 0; // Just to keep track


// EMULATE EXPRESS JS call ========================
const req = { body: { searchTerm: 1 } };
const res = {send: (val) => console.log('RECEIVED: ', val)};

const router = {
    post: (route, callback) => callback(req, res)
}

router.post('/', async (req, res) => {
    // Assign first query
    queries.push(req.body.searchTerm);
    // Invoke the async iterator
    const results = await queryIterator(queries);
    res.send(results);
});
// The Above is for nodeJS direct testing only, 
// > you can plug it into your own router.post declaration "as is"

// -----------------------------------------
// Define functions for Async Iterator -----

async function* queryGenerator() {
    while (true) {
        yield await onQueueSearch(queries.pop());
    }
}

async function queryIterator(queries) {
    for await (const result of queryGenerator()) {
        console.log('Iterating... ', result);
        console.log(`On Queue Searches #${++counter}: `, queries);
        if (!queries.length) {
            return result;
        }
    }
}

// ------------------------------------------------------------
// Emulate your current async requests using queries array ----

async function onQueueSearch(param) {
    return await longQuery(param);
}

async function longQuery(param) {
    if (param === 6) {
        // Use this as stop signal!
        return Promise.resolve(param);
    } else {
        queries.unshift(++param);
        return Promise.resolve(param);
    }
}

Возвращает:

/*
Iterating...  2
On Queue Searches #1:  [ 2 ]
Iterating...  3
On Queue Searches #2:  [ 3 ]
Iterating...  4
On Queue Searches #3:  [ 4 ]
Iterating...  5
On Queue Searches #4:  [ 5 ]
Iterating...  6
On Queue Searches #5:  [ 6 ]
Iterating...  6
On Queue Searches #6:  []
RECEIVED:  6
*/
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...