将 return 值从内部函数返回到父函数 - Javascript,Dynamics crm

Returning the return value from inner function to parent function- Javascript, Dynamics crm

下面的代码会return从内部函数到父函数displayButton()的boolean值吗?单击 Dynamics CRM 中的按钮会调用父函数。该函数应该 return 一个布尔值,具体取决于案例是否被选中以及所选的是活动的还是已解决的。

   //function called on click of a button in ms crm. 
    function displayButton()
    {
        var Obj = parent.Xrm.Page.getAttribute("regardingobjectid");
        var ObjValue = Obj.getValue();
        //parent.Xrm.Utility.alertDialog(" Value: " + ObjValue);
        if (ObjValue == null)
            return false;
        //else
        //    parent.Xrm.Utility.alertDialog(" Hi");

        var EntityType = ObjValue[0].entityType;

        var Guid = ObjValue[0].id;
        var id = Guid.slice(1, -1);
        //parent.Xrm.Utility.alertDialog(" Guid: " + id);

//Checking if regarding field is selected a case lookup value
        if (EntityType == "incident")
        {
            var req = new XMLHttpRequest();
            req.open("GET", parent.Xrm.Page.context.getClientUrl() + "/api/data/v8.2/incidents(" + id + ")?$select=statecode", true);
            req.setRequestHeader("OData-MaxVersion", "4.0");
            req.setRequestHeader("OData-Version", "4.0");
            req.setRequestHeader("Accept", "application/json");
            req.setRequestHeader("Content-Type", "application/json; charset=utf-8");
            req.setRequestHeader("Prefer", "odata.include-annotations=\"*\"");

            req.onreadystatechange = function ()
            {
                if (this.readyState === 4)
                {

                    req.onreadystatechange = null;
                    if (this.status === 200)
                    {

                        debugger;
                        var result = JSON.parse(this.response);

//checking if selected case is active or resolved.
                        var statecode = result["statecode"];

                        var statecode_formatted = result["statecode@OData.Community.Display.V1.FormattedValue"];
                        if (statecode_formatted == "Active") {
                            return true;

                        }
                        else if (statecode_formatted == "Resolved")
                            return false;
                        else {
                            return false;
                        }
                    }
                    else
                    {
                        parent.Xrm.Utility.alertDialog("Zero");
                    }


                }

            };
            req.send();

        }
        else {
            return false;
        }


    }

简短的回答是。内部函数被定义并分配给 req.onreadystatechangedisplayButton() 从不调用内部函数。因此它不会在此上下文中执行,因此不会 return 一个值。

可能这可以很好地深入挖掘 JS 中的函数:https://www.w3schools.com/js/js_function_definition.asp

没有。如果您想访问异步 XmlHttpRequest 返回的值,您需要将逻辑放在 if (this.status === 200) 范围内或提供回调。

您的 XMLHttpRequest 是异步的,因为此行中的 true 参数:

req.open("GET", parent.Xrm.Page.context.getClientUrl() + "/api/data/v8.2/incidents(" + id + ")?$select=statecode", true);

要提供回调,请将您的代码分成两个函数:

function getCaseState(id, callback) {
    var req = new XMLHttpRequest();
    req.open("GET", parent.Xrm.Page.context.getClientUrl() + "/api/data/v8.2/incidents(" + id + ")?$select=statecode", true);
    req.setRequestHeader("OData-MaxVersion", "4.0");
    req.setRequestHeader("OData-Version", "4.0");
    req.setRequestHeader("Accept", "application/json");
    req.setRequestHeader("Content-Type", "application/json; charset=utf-8");
    req.setRequestHeader("Prefer", "odata.include-annotations=\"*\"");

    req.onreadystatechange = function () {
        if (this.readyState === 4) {
            req.onreadystatechange = null;
            if (this.status === 200) {
                var result = JSON.parse(this.response);
                var statecode = result["statecode"];
                var statecode_formatted = result["statecode@OData.Community.Display.V1.FormattedValue"];

                callback(statecode_formatted);
            }
        }
    };
    req.send();
}

然后调用 getCaseState,将事件的 id 传递给它,并在请求准备好后调用一个函数:

// called on click of a button in CRM. 
function displayButton() {
    var regarding = parent.Xrm.Page.getAttribute("regardingobjectid").getValue();
    var entityType = regarding[0].entityType;
    var regardingId = regarding[0].id.slice(1, -1);

    // Check if regarding is an active case.
    if (entityType == "incident") {
        getCaseState(regardingId, function(state) {
            var isActive = state === "Active";

            if (isActive) {
                // TODO
            }
        });
    }
}

上面代码中传递的函数是匿名的——你应该把它进一步分离出来并命名它。

首先,您粘贴了太多代码。这是 Stack Overflow,你应该提供 Minimal, Complete, and Verifiable example 在不过多更改代码的情况下做到这一点的唯一方法是按照已经建议的那样将您的请求更改为同步,并将结果分配给在回调外部定义的某个变量。类似的东西:

function displayButton(){
    var result = false; //or true, depends what you want as default
    //some code
    //change it to synchonous request!!

    var req = new XMLHttpRequest();
    req.open("GET", parent.Xrm.Page.context.getClientUrl() + "/api/data/v8.2/incidents(" + id + ")?$select=statecode", false);
    //...
    req.onreadystatechange = function () {
         if (this.readyState === 4) {
             req.onreadystatechange = null;
             if (this.status === 200) {
                  //ommiting more code to get to the clue
                  //...
                  //...
                  if (statecode_formatted == "Active") {
                        result = true;
                    }
                    else if (statecode_formatted == "Resolved")
                        result = false;
                    else {
                        result = false;
                  }
             }
         }
     };
     req.send();

     return result;       
}

我不想更改您的整个代码,因为您粘贴了太多代码,但我相信您已经明白了。正如另一个答案中所建议的,您应该将调用函数移动到带有回调的单独函数,并在此回调中分配您的 "result" 。回调将同步 运行,因此该函数将 return 您的 "result" 具有适当的值。

你的XMLHttpRequest在这里是异步。所以你不能立即得到响应所以执行不会立即结束

我使用

解决了这个问题
setTimeout(function () {

  },550);

我觉得你可以试试下面的方法

这里我所做的改变是我将 XMLHttpRequest 保存在单独的 function 中,即 getResult(id) 并从父函数 调用 函数,即 displayButton().

并从子函数中 返回 值,我 将该布尔值设置为全局变量 var boolValue;

并且在父函数中在返回一个值之前我正在等待 550 亿秒 , 以便异步执行结束.

下面是代码片段。

父函数

var boolValue;

//function called on click of a button in ms crm. 
function displayButton() {
    var Obj = parent.Xrm.Page.getAttribute("regardingobjectid");
    var ObjValue = Obj.getValue();
    //parent.Xrm.Utility.alertDialog(" Value: " + ObjValue);
    if (ObjValue == null)
        return false;
    //else
    //    parent.Xrm.Utility.alertDialog(" Hi");

    var EntityType = ObjValue[0].entityType;

    var Guid = ObjValue[0].id;
    var id = Guid.slice(1, -1);
    //parent.Xrm.Utility.alertDialog(" Guid: " + id);

    //Checking if regarding field is selected a case lookup value
    if (EntityType == "incident") {
        getResult(id);

        setTimeout(function () {
            if(boolValue == true || boolValue == false)
            {
                return boolValue;
            }
        }, 550);

    }
    else {
        return false;
    }


}

子函数

function getResult(id)
{
    var req = new XMLHttpRequest();
    req.open("GET", parent.Xrm.Page.context.getClientUrl() + "/api/data/v8.2/incidents(" + id + ")?$select=statecode", true);
    req.setRequestHeader("OData-MaxVersion", "4.0");
    req.setRequestHeader("OData-Version", "4.0");
    req.setRequestHeader("Accept", "application/json");
    req.setRequestHeader("Content-Type", "application/json; charset=utf-8");
    req.setRequestHeader("Prefer", "odata.include-annotations=\"*\"");

    req.onreadystatechange = function () {
        if (this.readyState === 4) {

            req.onreadystatechange = null;
            if (this.status === 200) {
                var result = JSON.parse(this.response);

                //checking if selected case is active or resolved.
                var statecode = result["statecode"];

                var statecode_formatted = result["statecode@OData.Community.Display.V1.FormattedValue"];
                if (statecode_formatted == "Active") {
                    boolValue = true;
                }
                else if (statecode_formatted == "Resolved")
                    boolValue = false;
                else {
                    boolValue = false;
                }
            }
            else {
                parent.Xrm.Utility.alertDialog("Zero");
            }
        }
    };
    req.send();
}

这样解决了我的问题。