重复将请求发送到另一台服务器,直到获得预期结果

时间:2020-07-16 07:01:40

标签: javascript node.js

我正在请求服务器“ S”获取一些数据,但是此数据可能尚未准备好。

当数据尚未准备好时,服务器S会以{"data":null,"state": "pending"}进行响应,但是在准备好数据后,响应将类似于{"data": {...somedata}, "state": "done"}

我必须重复请求,直到数据准备就绪。我现在正在做的事情是这样的:

let wait = function* () {
  let t = 500;
  for (let j = 1; j < 10; j++) {
    yield new Promise((resolve) => {
      setTimeout(() => resolve(), t*=2);
    });
  }
}();

let result = await sendRequestToS();
status = result;
for (let i = 0; i < 4 && result.state==='pending'; i++) {
  await wait.next().value;
  result = await sendRequestToS();
}

如您所见,我最多发送4次请求,延迟为1、2、4和8秒。

我这样做正确吗? (使用 setTimeout 延迟请求之间的时间)不是不好的做法吗?

2 个答案:

答案 0 :(得分:1)

我会这样写:

function wait(ms) {
  return new Promise(res => setTimeout(res, ms));
}

async function requestAndRetry() {

  let retries = 10;
  let timeout = 1000;

  while(retries>0) {

    const response = await sendRequestToS();
    if (result?.state === 'done') {
      return result;
    }

    await wait(timeout);
    retries--;
    timeout*=2;

  }

  throw new Error('Request failed after 10 retries');

}

我认为这不是一个坏主意。这称为指数补偿,您并没有阻止脚本引擎。

答案 1 :(得分:0)

您可以直接使用async/await和递归来代替直接使用生成器。这是一个示例,它尝试获取有限次数的响应,以防止无限递归并且重试之间超时:

async function wait(timeInMs) {
  console.log('Waiting ...');
  return new Promise((resolve => setTimeout(() => resolve(), timeInMs)));
}


async function tryRequestToS(numberOfTries, timeout) {
  if (numberOfTries <= 0) {
     throw new Error("could net get result");
  }

  const result = await sendRequestToS();

  if (result && result.state === "done") {
    return result;
  }

  await wait(timeout); // wait for the defined timeout before recurring

  return tryRequestToS(numberOfTries - 1, timeout);
}

(async () => {
   try {
     const result = await tryRequestToS(10, 500); // max. 10 retries, 500 ms delay between retries
     console.log(result);
   } catch(err) {
     console.log(err);
   }
})();