Как я могу выполнить функцию с обещаниями и проверить ее значение несколько раз с помощью вызова API и выполнить другую функцию со значением?

#javascript #asynchronous #promise

Вопрос:

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

Теперь я знаю, что должен выполнить это Обещание, и я пытался это сделать, но я не уверен, правильно ли то, что я делаю.

Вот что я мог бы сделать с функцией обещания:

 const promiseFunc = ( param1, param2 ) => {

     return new Promise(( resolve, reject ) => {
           
          const func1 = api1( param1 );

          if ( func1.code === '200' ) {
      
                const startInterval = setInterval( () => {
 
                       const check = getValue();

                              if ( check amp;amp; check === param2 ) {
                                    clearInterval( startInterval );
                                    resolve();
                               } else {
                                    reject();
                               }
                       
                }, 5000);

          } else {
                reject();
          }

     });

}
 

Итак, в приведенной выше функции происходит то, что для вызова вызовов api требуется два параметра.
func1 выполняется, и если он возвращает 200, то запустите интервальный таймер. Пожалуйста, обратите внимание, что api1 вызов функции-это вызов API. Я попытался использовать await там, но он выдает ошибку. И я не уверен, могу ли я использовать асинхронность/ожидание внутри функции обещания.

Двигаясь дальше, check переменная начинает выполнять вызовы api ( getValue() это также функция, которая включает конечные точки api), чтобы проверить значение, доступно оно или нет. если это так, то разрешите, если нет, то отклоните.

Вот как я последовательно выполняю функцию promiseFunc:

 promiseFunc( myChosenValue1, myChosenValue2 )
     .then( data => {
            return promiseFunc( valueFromFirstExecution1, valueFromFirstExecution2 )       
     })
     .then( () => {
           console.log( 'Successfully executed both the functions' );
     })
     .catch( e => {
           console.log( e );
     });

 

Это самое большее, что я мог сделать при написании функции Promise, и я знаю, что в приведенном выше коде есть несколько проблем. Первая функция выполняется правильно, но затем я получаю эту ошибку TypeError: Cannot read property 'code' of undefined . Кроме того, я не уверен, будут ли выполняться вызовы API в setInterval. Есть какие-нибудь мысли?

Ответ №1:

Итак, у вас здесь происходит пара вещей:

  1. Вы хотите опросить процесс на стороне сервера для завершения
  2. Вы хотите вызвать другую функцию с результатом успешного завершения процесса на стороне сервера.

Так что давайте напишем несколько помощников:

 // We need a way to wait for some amount of time before
// retrying a request, sleep sleeps for n milliseconds
const sleep = (n) => new Promise(res => setTimeout(res, n));

// We need a unique sentinel value so we know when we have actual
// results from an API call instead of this default value
const sentinel = {}; // or Symbol, whatever unique you prefer

// poll will take the data necessary to make a fetch
// request and repeat it every `interval` milliseconds
// up to `maxRetries` until it gets a result
const poll = async (url, fetchOpts, interval, maxRetries) => {
  let result = sentinel; // default value
  let ticker = 0; // current number of retries
  while (result === sentinel amp;amp; ticker < maxRetries) {
    // make the api call
    const resp = await fetch(url, fetchOpts);
    const data = await resp.json();

    // do we have a result?
    if (isDone(data)) { // whatever criteria == completion
      result = data; // breaks the loop
    } else {
      // wait `interval` milliseconds and try again.
      ticker  ;
      await sleep(interval);
    }
  }

  // Oops! We didn't get an answer back from the
  // api in time
  if (result === sentinel) {
    throw new Error('Exceeded maxRetries!');
  }

  return resu<
};
 

Так что теперь мы действительно можем делать то, что хотим:

 // call this with the eventual result, *if* we
// get one
const onSuccess = (result) => {...}; // whatever

// This is doing the actual work
const doTheThing = async () => {
  await fetch(firstApiCall); // kick off the process
  try {
    // wait for completion
    const data = await poll(url, {}, 5000, 6); // ~30sec timeout

    // pass successful result onwards
    return onSuccess(data);
  } catch (err) {
    // Error bubbling is a little weird with async
    // functions, so we'll just handle it here and
    // return undefined
    console.error(err)
    return
  }
};
 

Комментарии:

1. Извини, приятель. Это выше моего понимания. Если бы вы могли немного объяснить, это было бы большой помощью.

2. @s.khan если я правильно понял, что вы хотели, вы хотите 1. использовать запрос api для запуска какого-либо процесса на вашем (или чьем-либо другом) сервере 2. продолжайте делать другой запрос api, пока не получите результат того, с чего вы начали (1) 3. если вы получите его обратно, передайте результат другой функции. Это точно?

3. ДА. Если я получу результат от первой функции, то выполню тот же вызов api, что и первый, но с другими параметрами.

4. @s.хан Ах, хорошо. На самом деле это не меняет ответа, просто вместо вызова какой-либо функции (например, той, которую я назвал «onSuccess»), вы просто снова выполните первый вызов API с data помощью ). Я просто добавил еще несколько комментариев, дайте мне знать, если все еще неясно.

5. Эй, чувак. Большое спасибо за ваше время. Тем не менее, я пытаюсь понять один вопрос. Функция выборки в опросе, это то же самое, что и это const check = getValue(); ? Или это то же const func1 = api1( param1 ); самое, что и ?