在履行承诺之前检查 url 状态

checking on url status before fulfilling a promise

我有一个 cypress 测试运行器的非典型用例,我需要从 cypress 中启动服务器。 我通过在 cypress plugins/index.js 中定义 before:spec 钩子来做到这一点,就像这样:

module.exports = (on, config) => {
    on('before:spec', async(spec) => {
        // the promise will be awaited before the runner continues with the spec
        return new Promise((resolve, reject) => {
            startServer();
            // keep checking that the url accessible, when it is: resolve(null)
 
            while (true) {
                getStatus(function(statusCode) {
                    if (statusCode === 200)
                        break
                })
            };
            resolve(null)

我正在努力实现这个 while 循环,它应该在履行 before:spec 承诺之前继续检查 url 是否可访问。 我有以下功能来检查 url:

function getStatus (callback) {
  const options = {
    hostname: 'localhost',
    port: 8080,
    path: '/',
    method: 'GET'
  }
  const req = http.request(options, res => {
  console.log(`statusCode: ${res.statusCode}`)
  callback(res.statusCode}
  })
  req.on('error', error => {
    console.error("ERROR",error)
  })
  req.end()

};

任何帮助实施该循环或其他建议如何在履行 before:spec 承诺之前完成检查 url 的任务表示赞赏。

理想情况下,您的 startServer 函数应该 return 一个 promise,并且在 before:spec 中简单地钩住您 await startServer();。或者至少应该接受在服务器初始化完成时调用的回调。但是让我们假设这是不可能的,所以这是给定代码的另一种解决方案:

function getStatus() {
    return new Promise((resolve, reject) => {
        const options = {
            hostname: 'localhost',
            port: 8080,
            path: '/',
            method: 'GET'
        }
        const req = http.request(options, res => {
            console.log(`statusCode: ${res.statusCode}`)
            resolve(res.statusCode);
        })
        req.on('error', error => {
            console.error("ERROR", error);
            reject(error);
        })
        req.end()
    });
};

module.exports = (on, config) => {
    on('before:spec', async (spec) => {
        // the promise will be awaited before the runner continues with the spec
            startServer();
            // keep checking that the url accessible, when it is: resolve(null)
            while (await getStatus() !== 200) {
                await (new Promise(resolve => setTimeout(resolve, 50)));
            }
    });
}

你最初的 while 循环尝试有严重的缺陷,因为你不能那样中断,你的服务器充满了请求。

目前只有一处奇怪,await (new Promise(resolve => setTimeout(resolve, 50))); 。这只是为了防止泛洪,如果服务尚未准备好,让我们给 50 毫秒。如果您知道您的服务启动速度确实较慢,请随意调整它,但更低的值没有多大意义。实际上它甚至不是绝对必要的,因为 while 循环中的条件确保一次只有一个请求 运行 。但我觉得这样更安全一些,如果它还在热身,那么频繁地尝试服务器是没有意义的。

另请注意,您可能希望在 req.on('error') 中 resolve(500) 或省略 resolve/reject,因为我不知道您的服务器是否立即准备就绪return 正确的状态代码,这取决于 startServer.

的实现