控制回调流程

时间:2017-08-29 18:39:24

标签: javascript node.js promise

我有以下Node.js代码。

index.js

"use strict";
// Close dialog with the user, reporting fulfillmentState of Failed or Fulfilled

var service = require("./service.js");

function dispatch() {
  const op = service.createIncident("enterpriseID", "shortDesc", function(
    incidentNo
  ) {
    if (incidentNo) {
      console.log("Index.js ServiceNow Incident:" + incidentNo);
      var msg = "Thank you! Your  Number is " + incidentNo;
      console.log("end of flow");
    } else {
      console.log("Index.js ServiceNow Incident:" + incidentNo);
      msg = "Err";
      console.log("end of flow");
    }
  });
  console.log("done");
}

dispatch();

这是我的service.js

var request = require("request-promise");
var servicenow = require("./configfile.json");

var snowURL = servicenow.url;
var snowUsername = servicenow.username;
var snowPassword = servicenow.password;
var ticketNo = "00000";

console.log(
  "Service Now URL:" +
    snowURL +
    " Username:" +
    snowUsername +
    " Password:" +
    snowPassword
);

module.exports = {
  createIncident: function(caller_id, short_description, callback) {
    var snowdetails = {
      uri: snowURL,
      json: {
        short_description: short_description
      },
      method: "POST",
      auth: {
        username: snowUsername,
        password: snowPassword
      }
    };

    request(snowdetails)
      .then(function(body) {
        var data = JSON.parse(JSON.stringify(body));
        ticketNo = data.result.number;
        console.log("Service Now Incident No:" + ticketNo);
        callback(ticketNo);
      })
      .catch(function(err) {
        console.log(err);
      });
  }
};

当我运行这个程序时,我得到输出为

Service Now URL:myUrl 
Username:myUserName Password:myPassword
done
Service Now Incident No:INC0010107
Index.js ServiceNow Incident:INC0010107
end of flow

但按照流程,我需要输出为。

Service Now URL:myUrl
Username:myUserName Password:myPassword
Service Now Incident No:INC0010107
Index.js ServiceNow Incident:INC0010107
end of flow
done

我知道这与回调和承诺有关,但并不是如何做到这一点。请帮我解决一下我应该如何更改输出流量(done被打印为最后一件事)

2 个答案:

答案 0 :(得分:0)

打印 done 的控制台语句不在回调中,所以在调用 service.createIncident 后立即执行。

它很容易修复,只需将日志语句移动到回调:

function dispatch() {
    const op = service.createIncident("enterpriseID", "shortDesc",
        function (incidentNo) {
            if (incidentNo) {
                console.log("Index.js ServiceNow Incident:" + incidentNo);
                var msg = "Thank you! Your  Number is " + incidentNo;
                console.log("end of flow");
            } else {
                console.log("Index.js ServiceNow Incident:" + incidentNo);
                msg = "Err";
                console.log("end of flow");
            }
            console.log("done");
        }
    );
}

答案 1 :(得分:0)

您应该做的第一件事是返回在其中创建的承诺 createIncident。通过执行此操作,无需将回调传递给createIncident,您可以直接从返回的承诺返回ticketNo,它将沿着承诺链传播。

请注意,此时通过附加catch处理程序,如果出现错误,链仍将继续。

createIncident: function (caller_id, short_description/*, callback*/) {
                                                  // ^ no need for callback with promises
  var snowdetails = {
    // ...
  };

  return request(snowdetails)
  // ^ return here
    .then(function (body) {
      var data = JSON.parse(JSON.stringify(body));
      ticketNo = data.result.number;
      console.log("Service Now Incident No:" + ticketNo);
      return ticketNo; // <-- propagate ticketNo through the promise chain
    }).catch(function (err) {
        console.log(err);
    });
}

dispatch而言,您现在可以将来电链接到service.createIncident并在ticketNo回调中收到incidentNo then

function dispatch() {
  return service.createIncident("enterpriseID", "shortDesc")
    .then(function (incidentNo) {
      if (incidentNo) {
        console.log("Index.js ServiceNow Incident:" + incidentNo);
        var msg = "Thank you! Your  Number is " + incidentNo;
        console.log("end of flow");
      } else {
        console.log("Index.js ServiceNow Incident:" + incidentNo);
        msg = "Err";
        console.log("end of flow");
      }
    });
}

dispatch()
  .then(function() {
    console.log("done");
  })