当“request / ajax”响应在nodejs bluebird中“成功”时,解决或拒绝承诺

时间:2015-08-05 06:01:54

标签: node.js promise 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需要几秒钟来处理视频,生成视频并将状态称为“成功”。然后我想反复继续调用api,并且只有在状态为“成功”时才解决承诺。带有无限while循环的代码不起作用。关于如何以最佳方式实现这一要求的任何建议。

2 个答案:

答案 0 :(得分:2)

你应该始终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;

答案 1 :(得分:1)

您不能将while()循环与异步操作一起使用。它将在任何一个API完成之前启动一系列API调用。相反,你必须对事物进行排序。进行一次API调用。获得结果后,请在结果处理程序中确定下一步操作。

另外,你没有做任何你正在创造的承诺,所以我决定从你的功能中回复承诺。

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

这里有一个想法,即如果你最终找到了成功"状态并在发生错误情况时被拒绝。

这实现了以下逻辑:

  1. 进行API调用。收到回复后,请执行以下四项操作之一。
  2. 如果回复是错误,请拒绝带有该错误的承诺
  3. 如果回复成功,请使用结果
  4. 解决承诺
  5. 如果响应不是错误,但尚未成功且您已超过最大重试次数,则拒绝最大重试次数
  6. 如果回复不是错误,但尚未成功,且您未超过最大重试次数,请重试
  7. 从函数返回一个promise,以便调用者可以在promise上使用.then()从操作中获取结果或错误
  8. 以下是代码:

    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();
        });
    }