【问题标题】:How to return a Promise after an XMLHttpRequest如何在 XMLHttpRequest 之后返回 Promise
【发布时间】:2020-08-13 13:14:56
【问题描述】:

我在 Dynamics 365 中调用函数 enableButton 来启用/禁用按钮。我必须向系统返回一个 Promise。如果我执行一个返回 Promise 的简单测试函数,这可以正常工作,但我需要获取一个令牌,然后对服务进行外部调用以设置 true/false,然后返回 Promise。当我这样做时,它不起作用。似乎 Dynamics 永远不会从函数中获得 Promise。

这是我的代码(我已经发布了一些细节)。我只在 Dynamics 中调用 enableButton()。

function enableButton() {
    var params = getParams();
    var xhr = new XMLHttpRequest();
    xhr.open("POST", "http://my.tokenendpoint.com");
    xhr.onload = function () {
        var token = JSON.parse(xhr.response).access_token;
        getExternalData(token, ssn);
    }
    xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
    xhr.send(params);
}

function getExternalData(token) {
    return new Promise(function (resolve, reject) {
        var url = "http://example.com"
        var query = JSON.stringify(
            {
                "queryparams": true
            }
        );

        var xhr = new XMLHttpRequest();
        xhr.open("POST", url);
        xhr.onload = () => {
            if (xhr.readyState === xhr.DONE) {
                if (xhr.status === 200) {
                    var data = JSON.parse(xhr.responseText);
                    var hasExternalData = hasExtData(data[0]); //returns a boolean
                    resolve(hasExternalData);
                }
                else {
                    reject(xhr.statusText);
                }
            }
        };
        xhr.onerror = function (e) {
            reject(xhr.statusText);
        };

        xhr.setRequestHeader("Authorization", "Bearer " + token);
        xhr.setRequestHeader("Content-Type", "application/json");
        xhr.send(query);
    });
}

我已经使用 fetch 重写了代码,但我没有收到正确的数据以返回给 Dynamics。

如果我在 Dynamics 中使用类似这样的简单函数进行测试,它可以工作:

function enableButton() { 
    return new Promise(function (resolve, reject) {
                var test = true; 
                resolve(test); 
            }, 
            function (error) { 
                reject(error.message); 
                console.log(error.message); 
            } 
        ); 
    }

如果我这样做,它不起作用:

function enableButton() { 
    fetch(accesstokenUrl, {
        method: 'POST',
        body: <omitted params>
        headers: {
            'Content-Type': 'application/x-www-form-urlencoded'
        }
    })
        .then(function (response) {
            return response.json();
        })
        .then(function (resJson) {
            return fetch(url, {
                method: 'POST',
                headers: {
                    'Authorization': 'Bearer ' + resJson.access_token,
                    'Content-Type': 'application/json'
                },
                body: JSON.stringify(
                    {
                        "queryparams": true
                    })
            });
        })
        .then(function (res) {
            return res.json();
        })
        .then(function (data) {
         const hasDebtCase = getDebtCase(data);
              if (hasDebtCase) {
                return Promise.resolve(hasDebtCase);
            } else {
                return Promise.reject(data);
            }  
        })
        .catch((error) => {
            console.error('Error:', error);
        })
};

我的问题是什么?

【问题讨论】:

  • 不要使用 XMLHttpRequest,它早就过时了。请改用fetch,它会根据需要返回一个承诺。
  • 查看此页面以了解如何承诺功能:javascript.info/promisify
  • 所以 enableButton 应该是一个承诺...不清楚承诺是什么,因为你不使用它。
  • 我希望函数 enableButton 在检查 hasDebtCase 后返回 promise resolve/reject。

标签: javascript promise xmlhttprequest dynamics-365


【解决方案1】:

请参阅下面有关在 Dynamics CRM 中使用启用规则时如何返回承诺的文章。 https://ajitpatra.com/2019/12/11/d365-enable-rule-for-button-with-asynchronous-api-request-using-promise/?utm_campaign=Dynamics%20Weekly&utm_medium=email&utm_source=Revue%20newsletter

如果我有帮助,请标记我的答案已验证

【讨论】:

    【解决方案2】:

    在您的情况下,最好将 async/await 与 fetch 一起使用。

    async function enableButton() { 
        const responseA = await fetch(accesstokenUrl, {
            method: 'POST',
            body: {
                    "access_token": "123"
            },
        });
       const responseAJson = await responseA.json();
       console.log("Response from the first fetch", responseAJson);
       console.log("Your Access Token", responseAJson.access_token);
       
       const responseB = await fetch(url, {
            method: 'POST',
            headers: {
                'Authorization': 'Bearer ' + responseAJson.access_token,
                'Content-Type': 'application/json'
            },
            body: JSON.stringify(
                {
                    "queryparams": true
                })
        });
        console.log("Response from the second fetch", await responseB.json());
        
        const hasDebtCase = getDebtCase(responseB.json());
        if (hasDebtCase) {
            return Promise.resolve(hasDebtCase);
        } else {
            return Promise.reject(data);
        }  
     }
    

    【讨论】:

    • 我没有尝试过这种方法。谢谢,我试试看。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-09
    • 2019-05-28
    • 2016-02-14
    • 2020-08-06
    • 1970-01-01
    • 2017-05-07
    • 1970-01-01
    相关资源
    最近更新 更多