如何执行带有承诺的函数并通过 API 调用多次检查其值并使用该值执行另一个函数?

Posted

技术标签:

【中文标题】如何执行带有承诺的函数并通过 API 调用多次检查其值并使用该值执行另一个函数?【英文标题】:How can I execute a function with promises and check its value multiple times by API call and execute another function with the value? 【发布时间】:2021-12-20 03:35:38 【问题描述】:

我正在开发一个应用程序,我需要在函数中进行 API 调用,然后使用其值进行另一个 API 调用。但是第一个 API 调用的值并不容易获得,因为它取决于一些外部因素。因此,在进行第一次 API 调用后,我需要以 5 秒的间隔进行 3 次 API 调用,以检查该值是否可用。如果是,则进行第二次 API 调用,否则不要进行第二次 API 调用。

现在我知道我必须这样做 Promises 并且我尝试这样做,但我不确定我所做的是否正确。

这就是我可以对 Promise 函数做的事情:

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 && check === param2 ) 
                                    clearInterval( startInterval );
                                    resolve();
                                else 
                                    reject();
                               
                       
                , 5000);

           else 
                reject();
          

     );


所以在上面的 func 中发生的事情是它需要两个参数来调用 api 调用。 func1 被执行,如果它返回 200 则启动间隔计时器。请注意,api1 函数调用是 API 调用。我尝试在那里使用 await 但它会引发错误。而且我不确定我是否可以在 Promise 函数中使用 async/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。另外,我不确定 setInterval 中的 API 调用是否会运行。有什么想法吗?

【问题讨论】:

【参考方案1】:

所以你有几件事在这里发生:

    您想要轮询服务器端进程以完成 您想使用服务器端进程成功完成的结果调用另一个函数。

所以让我们写一些助手:

// 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 && 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 result;
;

所以现在我们可以真正做我们想做的事了:

// 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
  
;

【讨论】:

对不起,伙计。它在我的头上。如果你能解释一下,那将是一个很大的帮助。 @s.khan 如果我理解你想要的正确,你想要 1. 使用 api 请求在你(或其他人的)服务器上启动一些进程 2. 继续发出另一个 api 请求,直到你取回您使用 (1) 启动的结果 3. 如果您取回它,则将结果传递给另一个函数。准确吗? 是的。如果我从第一个函数中得到结果,则进行与第一个函数相同的 api 调用,但参数不同。 @s.khan 好的。不过,这并没有真正改变答案,只是不用调用某个函数(比如我命名为“onSuccess”的那个),而是用data 再次调用第一个API)。我刚刚添加了一些 cmets,如果还不清楚,请告诉我。 嘿伙计。非常感谢您的时间。但是,我试图理解一个问题。 poll 中的 fetch 函数,和 const check = getValue(); 一样吗?还是和const func1 = api1( param1 );一样?

以上是关于如何执行带有承诺的函数并通过 API 调用多次检查其值并使用该值执行另一个函数?的主要内容,如果未能解决你的问题,请参考以下文章

带有等待和承诺的 useMutation 问题

如何使用 Promise Kit 调用递归函数?

节点递归承诺永远不会退出

处理带有承诺的对象数组

如何检查 Promise 是不是处于待处理状态 [重复]

如何在带有命令行参数的 vbscript 中调用函数?