关于在SOAP API调用期间使用Async/Await的问题,JavaScript中存在以下问题:

huangapple go评论68阅读模式
英文:

Issues with Async/Await during SOAP API call Javascript

问题

PSA_Resultbody = ProcessPSAAPI(xmlpackage, PSA_Action);
console.log("3 - Returned data:" + PSA_Resultbody);

async function ProcessPSAAPI(xmlpackage, PSA_Action) {
var options = {...};
var req = https.request(options, function (res) {
var chunks = [];
res.on("data", function (chunk) {
chunks.push(chunk);
});

res.on("end", function (chunk) {
  var body = Buffer.concat(chunks);
  console.log('0 - Start ' + body.toString());
  if (res.statusCode != 200) {
    PSA_Resultcode = "Error: " + res.statusCode + " - " + res.statusMessage;
  } else {
    PSA_Resultcode = "Success: " + res.statusCode + " - " + res.statusMessage;
    PSA_Resultbody = ParseResults(body.toString()); 
    console.log("1 - PSA_Resultbody as part of RES =" + PSA_Resultbody);
  }
  console.log('2 - RESULT BODY BEFORE SENDING BACK TO INITIATING FUNCTION: ' + PSA_Resultbody);
  // Move this console log here to ensure it's printed in the correct order.
});

res.on("error", function (error) {
  console.error(error);
  PSA_Resultcode = res.statusCode + " - " + res.statusMessage;
});

});

req.write(xmlpackage);
req.end();
// Return PSA_Resultbody outside of the request callback.
return PSA_Resultbody;
}

英文:

Hopefully someone can point me to the right direction. I read up on waiting for functions to complete before continuing and I resolved myself to using await/async but I am just stuck now.

I tried to get the Async/Await process to work, tried to inject the await in various locations, with adjusting the functions to be async, but i can not get the PSA_Resultbody to return to the original request. Any pointers would be appreciated.

Thank you,

CE

PSA_Resultbody = ProcessPSAAPI(xmlpackage, PSA_Action);
console.log("3 - Returned data:" + PSA_Resultbody);

calls the below:

async function ProcessPSAAPI(xmlpackage, PSA_Action) {  //psa action is part of the options

  var options = {...};
  var req = https.request(options, function (res) {
    var chunks = [];
    res.on("data", function (chunk) {
      chunks.push(chunk);
     });
  
    res.on("end", function (chunk) {
      var body =  Buffer.concat(chunks);
      console.log('0 - Start '+body.toString());
      if(res.statusCode != 200) {
         PSA_Resultcode = "Error: " +res.statusCode +" - "+ res.statusMessage;
        } else {
         PSA_Resultcode = "Success: " +res.statusCode +" - "+ res.statusMessage;
         PSA_Resultbody = ParseResults(body.toString()); //parse the results for later use  --SCRIPT NEEDS TO WAIT FOR RESULTBODY TO COMPLETE
                console.log("1 -PSA_Resultbody as part of RES = "+PSA_Resultbody);
        } 
     });
    res.on("error", function (error) {
      console.error(error);
      PSA_Resultcode = res.statusCode +" - "+ res.statusMessage;
     });

   });
   console.log('2 -RESULT BODY BEFORE SENDING BACK TO INITIATING FUNCTION: '+PSA_Resultbody);
   req.write(xmlpackage);
   req.end();
  return PSA_Resultbody;

Based on the above, my console log order is: 3,2,0,1 in stead of 0,1,2,3.

0 and 1 will have the correct data, so the API Call does work, but 2 will be "undefined" and should have the same data that is in 1.

答案1

得分: 1

没有办法等待事件发射器,因此在这种情况下使用async是没有用的。你也不能从事件内部“返回”。

解决方案是返回一个新的自定义Promise,并在发射器的“end”事件内使用resolve()。

它会像这样:

function ProcessPSAAPI(xmlpackage, PSA_Action) {
  return new Promise((resolve, reject) => {
    // 其他代码
    res.on("end", function (chunk) {
      // 其他代码
      resolve(PSA_Resultbody);
    });
    res.on("error", function (error) {
      // 其他代码
      reject(error);
    });
  });
}

这是一个我写的快速教程,用于创建你自己的Promise,我写这个教程是为了简化这个主题的理解(官方文档在我看来有点枯燥和复杂)。

英文:

There's no way to await an event emitter, so using async in this case isn't going to be useful. You cannot "return" from inside an event either.

The solution here is to return a new custom promise and to use resolve() inside of the "end" event of your emitter.

It will look something like this:

function ProcessPSAAPI(xmlpackage, PSA_Action) {
  return new Promise( (resolve, reject) => {
    // other code
    res.on("end", function (chunk) {
      // other code
      resolve(PSA_Resultbody);
    });
    res.on("error", function (error) {
      // other code
      reject(error);
    });
  });
}

Here's a quick tutorial on creating your own promises, which I've written to simplify comprehension of the subject (official docs are somewhat dry and complex imho).

答案2

得分: 0

我没有改变你的代码。我只是添加了适当的Promise结构以帮助你入门。这实际上应该是一个关于Promise的教程。async await是Promise的一种缩写结构。Promise是等待代码执行的一种方式。它可以被看作是在Promise解决时将执行的回调函数数组。

一个简单的Promise的工作方式如下:

const myPromise = new Promise(function(resolve, reject) {
    /* 在这里编写你的逻辑。可以是任何内容。
     * 但重要的是要记住,当你成功时,要调用resolve。
     * 当你失败时,要调用reject。
     */
    someCallBackPattern(function(error, data) {
        if(error) {
            reject(error);
        } else {
            resolve(data);
        }
    });
});

// 要获取数据,你可以使用'then'和'catch'。then有两个参数。

myPromise.then(function(data) {
    // 第一个参数是resolve的结果。
}, function(err) {
    // 第二个参数是reject的结果。
}).catch((err) => {
    // 你也可以从catch回调中获取错误。
});

这有点混乱和复杂。所以有了async await。

async function someFunction () { // 除非在await函数中,否则无法等待结果
    PSA_Resultbody = await ProcessPSAAPI(xmlpackage, PSA_Action); // 等待你的结果。
    console.log("3 - 返回的数据:" + PSA_Resultbody);
}

function ProcessPSAAPI(xmlpackage, PSA_Action) { // 这不需要是async,除非在其中等待。
    return new Promise((resolve, reject) => { // async await是Promise的一种缩写结构。虽然你不一定要使用Promises,但正确的结构会有很大帮助。
        var options = {...};
        var req = https.request(options, function (res) {
            var chunks = [];
            res.on("data", function (chunk) {
                chunks.push(chunk);
            });

            res.on("end", function (chunk) {
                var body =  Buffer.concat(chunks);
                console.log('0 - 开始 ' + body.toString());
                if(res.statusCode != 200) {
                    PSA_Resultcode = "错误:" + res.statusCode + " - " + res.statusMessage;
                    reject(new Error(PSA_Resultcode)); // 拒绝你的错误
                } else {
                    PSA_Resultcode = "成功:" + res.statusCode + " - " + res.statusMessage;
                    PSA_Resultbody = ParseResults(body.toString()); //解析结果以供以后使用  --脚本需要等待RESULTBODY完成
                    console.log("1 - PSA_Resultbody 作为RES的一部分 = " + PSA_Resultbody);
                    resolve(PSA_Resultbody); // 解决你的结果
                } 
            });
            res.on("error", function (error) {
                console.error(error);
                PSA_Resultcode = res.statusCode + " - " + res.statusMessage;
                reject(new Error(PSA_Resultcode)); // 拒绝你的错误
            });
        });
        console.log('2 - 发送回初始函数之前的RESULT BODY:' + PSA_Resultbody);
        req.write(xmlpackage);
        req.end();
    })
}

这就是它的工作原理。

英文:

I did not change your code. I just put the appropriate promise structure in to get you started. This should really be a lesson in promises. async await is a shorthand promise structure. A Promise is one way you wait on code. It can be thought of as an array of callbacks that will be executed when the Promise is resolved.

A simple promise works like this:

const myPromise = new Promise(function(resolve, reject) {
/* Your logic goes in here. It can be anything. 
* But the important part to remember is that when you have success, resolve it. 
* When you have a failure, reject it.
*/
someCallBackPattern(function(error, data) {
if(error) {
reject(error);
} else {
resolve(data);
}
});
});
// To get the data out you use 'then', and 'catch'. then has two arguments.
myPromise.then(function(data) {
// The first argument is the result from resolve.
}, function(err) {
// The second argument is the result from reject.
}).catch((err) => {
// you can also get to the error from the catch callback
});

This is kinda messy and complex. So there is async await.

async function() {
try {
const result = await myFunctionThatReturnsAPromise();
// result is the resolved data
} catch (err) {
// err is the rejected Error
}
}
function myFunctionThatReturnsAPromise() {
return new Promise((resolve, reject) => {
// your code
})
}

And thats how it works.

async function someFunction () { // You can not wait on results unless you are in an await function
PSA_Resultbody = await ProcessPSAAPI(xmlpackage, PSA_Action); // await on your results.
console.log("3 - Returned data:" + PSA_Resultbody);
}
function ProcessPSAAPI(xmlpackage, PSA_Action) { // This does not need to be async. Unless you are awaiting in it.
return new Promise((resolve, reject) => { // async await is a shorthand promise structure. Although you do not need to use promises. It really helps to get the structure correct.
var options = {...};
var req = https.request(options, function (res) {
var chunks = [];
res.on("data", function (chunk) {
chunks.push(chunk);
});
res.on("end", function (chunk) {
var body =  Buffer.concat(chunks);
console.log('0 - Start '+body.toString());
if(res.statusCode != 200) {
PSA_Resultcode = "Error: " +res.statusCode +" - "+ res.statusMessage;
reject(new Error(PSA_Resultcode)); // Reject you errors
} else {
PSA_Resultcode = "Success: " +res.statusCode +" - "+ res.statusMessage;
PSA_Resultbody = ParseResults(body.toString()); //parse the results for later use  --SCRIPT NEEDS TO WAIT FOR RESULTBODY TO COMPLETE
console.log("1 -PSA_Resultbody as part of RES = "+PSA_Resultbody);
resolve(PSA_Resultbody); // Resolve your result
} 
});
res.on("error", function (error) {
console.error(error);
PSA_Resultcode = res.statusCode +" - "+ res.statusMessage;
reject(new Error(PSA_Resultcode)); // Reject you errors
});
});
console.log('2 -RESULT BODY BEFORE SENDING BACK TO INITIATING FUNCTION: '+PSA_Resultbody);
req.write(xmlpackage);
req.end();
})
}

huangapple
  • 本文由 发表于 2020年1月4日 00:20:01
  • 转载请务必保留本文链接:https://go.coder-hub.com/59581877.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定