在 nodejs bluebird 中 "request/ajax " 响应为 'success' 时解决或拒绝承诺

resolve or reject promise when "request/ajax " response is 'success' in nodejs bluebird

我不熟悉将 promises 与 bluebird 结合使用。 当状态响应从 api 更改为 "success" 时,我正在尝试解决承诺。 下面是我的代码:

exports.getdata(taskCreation, headers) {
  var deferred = Promise.pending();

  var headers = {
    "Authorization": "Secret xxxxxxxxxxxxxxxxx"
  };

  while (true) {
    request.get({
      url: "https://dragon.stupeflix.com/v2/status",
      qs: {
        tasks: taskCreation[0]["key"]
      },
      headers: headers,
      json: true
    }, function (error, httpObj, taskStatusAndResult) {
      if (!error && httpObj.statusCode == 200) {
        console.log(taskStatusAndResult[0]["status"]); //contains either "queued", "executing", "success", or "error"
        if (taskStatusAndResult[0]["status"] == "success")
          deferred.resolve(taskStatusAndResult);

      } else {
        deferred.reject(error);
      }
    })
  }
        return deferred.promise;
}

api 需要几秒钟来处理视频,生成视频 url 并将状态设置为 "success"。在那之前我想重复调用 api,并且只有在以下情况下才解决承诺状态是 "success"。我的带有无限 while 循环的代码不起作用。关于如何以最佳方式实现此要求的任何建议。

您不能将 while() 循环与异步操作一起使用。它会在任何一个调用完成之前启动无数个 API 调用。相反,您必须对事物进行排序。打一个 API 电话。获得结果后,在该结果处理程序中决定下一步要做什么。

此外,您没有对您创建的承诺做任何事情,所以我决定 return 您的函数中的承诺。

而且,您的 exports.getData 声明不是正确的函数声明。


这是一个想法,你 return 一个承诺,如果你最终找到 "success" 状态,承诺就会被解决,如果出现错误情况,承诺就会被拒绝。

这实现了以下逻辑:

  1. 拨打 API 电话。收到回复后,请执行以下四项操作之一。
  2. 如果响应是错误的,则拒绝具有该错误的承诺
  3. 如果响应成功,用结果解决承诺
  4. 如果响应不是错误,但尚未成功并且您已超过最大重试次数,则拒绝最大重试次数
  5. 如果响应不是错误,但尚未成功并且您没有超过最大重试次数,请重试
  6. Return 来自函数的承诺,因此调用者可以仅在承诺上使用 .then() 来获取操作的结果或错误

代码如下:

exports.getdata = function (taskCreation, headers) {
    var headers = {"Authorization": "Secret xxxxxxxxxxxxxxxxx"};
    var cntr = 0;
    var maxRetries = 20;

    return new Promise(function (resolve, reject) {
        function next() {
            ++cntr;
            request.get({
                url: "https://dragon.stupeflix.com/v2/status",
                qs: {tasks: taskCreation[0]["key"]},
                headers: headers,
                json: true
            }, function (error, httpObj, taskStatusAndResult) {
                if (!error && httpObj.statusCode == 200) {
                    console.log(taskStatusAndResult[0]["status"]); //contains either "queued", "executing", "success", or "error"
                    if (taskStatusAndResult[0]["status"] === "success") {
                        // found success to resolve the promise
                        resolve(taskStatusAndResult);
                    } else {
                        // if not "success" yet, then try again
                        if (cntr > maxRetries) {
                            reject(new Error("max retries exceeded"));
                        } else {
                            // try again
                            next();
                        }
                    }
                } else {
                    // got some kind of error here, so stop further processing
                    reject(error);
                }
            })
        }
        // start the first request
        next();
    });
}

你应该总是promisify在尽可能低的级别,这样你就可以对其他一切使用承诺。

function makeRequest() {
  return new Promise(function(resolve, reject) {
    request.get({
      url: "https://dragon.stupeflix.com/v2/status",
      qs: {
        tasks: taskCreation[0]["key"]
      },
      headers: {
        "Authorization": "Secret xxxxxxxxxxxxxxxxx"
      },
      json: true
    }, function (error, httpObj, taskStatusAndResult) {
      if (error) reject(error);
      else if (httpObj.statusCode != 200) reject(httpObj); // or so
      else resolve(taskStatusAndResult);
    });
  });
}

现在我们可以使用 promise 语法来编码您的应用程序用例,在本例中是一种递归算法,它会重试请求直到它获得 success:

function getData(taskCreation, headers) {
  return makeRequest(taskCreation, headers).then(function(taskStatusAndResult) {
    if (taskStatusAndResult[0]["status"] == "success")
      return taskStatusAndResult;
    else
      return getData(taskCreation, headers); // do it again
  });
}
exports.getdata = getData;