【问题标题】:NodeJS - Promise callback response [SyntaxError: Unexpected end of input]NodeJS - 承诺回调响应 [SyntaxError: Unexpected end of input]
【发布时间】:2016-10-25 01:30:37
【问题描述】:

我创建了以下 NodeJS 函数。

我遇到的问题是,当我执行以下代码时:

someFunc(parameter)
.then(function(doSomething){
  //do something here, which works fine here.
})
//The following function works and is very similar to the next function.
.then(someFunc1)
//
.then(impervaCreateIP)
//
//The following function works and is very similar to the above function.
.then(someFunc3)
.catch(function(e){
  //catch error here. This works too.
})

并调用下面的函数,它给了我一个错误:

[SyntaxError: Unexpected end of input]

出现此错误是因为,当函数 (someFunc1) 成功完成后控件转到 impervaCreateIP() 时,然后在 impervaCreateIP() 内部,以下几行是正在执行(等待 REST/API 调用以在 Imperva 系统中创建新的 OS 连接 IP)。

  httpHelp(options, data)
  .then(function(fullResponse){
    var result = JSON.parse(fullResponse[1])

正如你在上面看到的,一旦 httpHelp(options,data).then(function(fullResponse){ ... } 部分被调用,如果我打印 (console.log("anything")) 就在下一行之前,它显示该消息很好。但是,在下一行之后没有打印任何内容,原因:fullResponse[1] 没有得到填充或没有得到任何有效值,由以异步方式执行以下行的时间。这导致程序直接进入 .fail(...){ .. } 部分,然后进入 someFunc3 (在 impervaCreateIP 和终于到达 .catch(...){ .. } 部分并做我在那里做的任何事情。

    var result = JSON.parse(fullResponse[1])

因此,程序在 . 字符的 .parse 处出错,即它无法将变量 result 解析为 strong>fullResponse[1] 值仍设置为“”(空白/NULL),尚未填充。

如何,我可以让我的程序等待,即直到 httpHelp(..).then(function(fullResponse) {.. } 完全完成与 REST/API 调用的工作并在内部返回一个有效值fullResponse[1]

PS:我看到 fullResponse[0].statusCode == 200,所以连接很好。

代码:

//Imperva create IP
//qData is a hash array that has valid index/value pair values.
var impervaCreateIP = function(qData){
  var deferred = Q.defer();
  var data = '{"connection-mode":"SSH","host-name":"server123.company.com"}'
  var options = {
    hostname: 'myImpervaServerInstance.mycompanydomain.com',
    port: 8083,
    method: 'POST',
    path: '/SecureSphere/api/v1/conf/serverGroups/'+ qData['siteName'] + '/' + qData['serverGroupName'] + '/servers/' + qData['ip'],
    headers: {
      'Content-Type': 'application/xml',
      'X-Requested-With': 'Nodejs',
      'Cookie': 'JSESSIONID='+qData['sid']
    }
  }
  //svtLog() is a logger that I'm using to log messages to a file. Out of scope of this post.
  svtLog('info','Imperva','Inside impervaCreateIP function')
  svtLog('info','Imperva',qData['ip'])
  svtLog('info','Imperva',qData['siteName'])
  svtLog('info','Imperva',qData['serverGroupName'])
  console.log('Inside impervaCreateIP')
  console.log(options);
  httpHelp(options, data)
  .then(function(fullResponse){
    //The following section is not executing
    console.log("00 ---- this will print fine")
    var result = JSON.parse(fullResponse[1])
    //The following section is not executing. It going straight to .catch() as the above line failed at .parse(fullResponse[1]) where fullResponse[1] is coming as BLANK.
    console.log("11 -----")
    console.log(result)
    console.log("22 -----")
    deferred.resolve(qData)
    console.log(result)
  })
  .fail(function(e){
    svtLog('error','Imperva','Failed to add IP in Imperva')
    svtLog('info','Imperva',qData['ip'])
    svtLog('error','Imperva',e)
    svtLog('info','Imperva','')
    deferred.reject(e)
  })
  return deferred.promise;
}

fullResponse(数组值的快照是)在 someFunc1/3 或 ImpervaCreateIP 的情况下。我只显示最后 5 行。我确保两个文件的 head -5 看起来相同,并且 fullResponse[0] 索引值也基本相似:

[vagrant@localhost ws]$ cat -n someFunc1.ip.fullResponse.json |tail -5; echo ----------------; cat -n create.ip.fullResponse.json |tail -5
   230         parser: null,
   231         res: [Circular] },
   232      read: [Function] },
   233    '{"ip":"10.20.30.40","domain":"","connection-mode":"SSH","share-name":"","folder-path":"","user-name":"enter_your_userID","host-name":"test-imperva-clientserver01.cloud.mycompany.com","OS-type":"Linux"}' ]
   234
----------------
   233         parser: null,
   234         res: [Circular] },
   235      read: [Function] },
   236    '' ]
   237
[vagrant@localhost ws]$

如果您注意到,someFunc1.ip.fullResponse.json 文件中的第 232 行和第 233 行,第 232 行结束 fullResponse[0],第 233 行开始 fullResponse[1] 值。在我的例子中,假设 someFunc1 是为了找到一个 IP,上面的输出显示,REST/API 返回值 fullResponse[1] 使用 Imperva REST/API(其中方法是 GET)查找 IP 的值,其余代码完全相同到 impervaCreateIP()。

如果您注意到 create.ip.fullResponse.json 文件的第 235 行和第 236 行,您会看到第 235 行结束了 fullResponse[0] 数组索引值,第 236 行开始了 fullResponse[1 的值] 并且其中有一个 '' (Blank/NULL),这意味着,在使用 impervaCreateIP 创建 IP 时,它DID NOT在 fullResponse[1] 数组索引中接收到来自 Imperva REST/API 的有效响应由

使用
var result = JSON.parse(...); // line in my NodeJS code above.

同样,someFunc1(查找 IP)或 impervaCreateIP(创建 IP)之间的唯一主要区别是,除此之外,只有 console.log("...") 消息有所改变:

对于 impervaCreateIP,它设置为:

method: 'POST',

对于 someFunc1,它设置为:

method: 'GET',

好的,看来问题出在我的 methodPOST/DELETE + 时> 当我使用 var result = JSON.parse(fullResponse[1]).

如果我不尝试使用上面提到的 var result / JSON.parse 检查任何内容,我的代码可以正常工作。

所以,我认为我的根本原因是:如果我的 REST/API HTTP 方法是 POSTDELETE,由于某种原因没有填充 fullResponse[1] >。如果我使用任何状态检查,例如在 impervaCreateIP(POST 操作)之后在 someFunc3(即方法为 DELETE 的 impervaDeleteSessionID)之后发生的情况,那么我的程序是工作正常,我的错误消息消失了。

但是,我确实想验证 REST 响应的内容 for ex:以便我可以了解 REST 连接是否有效 + 如果创建 IP 操作由于权限问题而失败对于我用来生成我的 JSESSIONID 的凭据的那个用户。只有当它的 POST/DELETE 并且我正在做 JSON.parse(fullResponse[1])

当 HTTP 方法是“POST”或“DELETE”时,我如何获取上述 NodeJS 代码中的响应正文,并且我想捕获下面提到的条件??谢谢。

仅供参考: 当我在 BASH shell 脚本中尝试相同的 impervaCreateIP NodeJS 逻辑时,我编写了以下代码并且它可以工作!!!因为 CURL 命令返回所有输出的好坏,即如果在创建 IP 脚本期间由于该用户凭据的访问问题而出现错误,则返回有效的响应代码。 我想要在 NodeJS 代码中做的所有事情就是捕获“没有权限”错误,如果 USER 没有足够的权限来 CREATE Imperva 系统中的一个 IP:

## Create a new IP OS connection in a given site, server group.
create_ip()
{
 JSESSIONID="${1}"
 addThisIP="${2}"
 siteName="${3}"
 serverGroupName="${4}"
 echo -e "\n- Trying to create a new OS connection IP now.\n";

 ##Make sure while initiating a REST API call, any parameter which has ' ' (space) in Imperva should be substituted with '%20'.
 create_new_ip_output="$(curl -ik -X POST -H "Cookie: JSESSIONID=$JSESSIONID" -H "Content-Type: application/json" -H "Accept: application/json" "https://${MX}:8083/SecureSphere/api/v1/conf/serverGroups/${siteName// /%20}/${serverGroupName// /%20}/servers/${addThisIP}" -d '{"connection-mode":"SSH","host-name":"thisLinuxServer.fdqn","OS-type":"linux","user-name":"enter_your_userID"}')";
 return_code="$?";
 if [[ "${return_code}" == "0" && ! `echo "${create_new_ip_output}" | grep "do not have permission"` ]]; then
  echo -e "\n\n- OS connection IP (${addThisIP}) created successfully in site: ${siteName}, servergroup: ${serverGroupName} and stdout:\n${create_new_ip_output}\n";
  return 0;
 else
  echo -e "\n\n- Failed to create a new OS connection IP (${addThisIP}) in site: ${siteName} and servergroup: ${serverGroupName}\n- using session ID: ${JSESSIONID}, error log:\n${create_new_ip_output}\n";
  return 1;
 fi
}

【问题讨论】:

  • fullResponse 到底是什么?我怀疑你用错了。
  • @KevinB,我是新手,在线尝试了几种解决方案,但对为什么同样适用于 someFunc1 感到困惑?为什么 NodeJS 是异步 n 单线程正在等待完成(当 someFunc1 时)在我的情况下需要 30 秒。 fullResponse 是一个包含 2 个索引的数组,[0].statusCode 显示它已成功建立连接 == 200 响应代码,但 [1] 以 ' ' 的形式出现,因此结果变量 JSON.parse 失败
  • 我认为您误诊了问题。如果您看到状态 200,那么它实际上正在等待。它至少在等待发送请求和开始接收响应。我不知道是否对 httpHelp 进行了编码以正确侦听所有数据块并将它们组合成正确的 json 字符串。
  • 可能是因为 someFunc1 编码正确?
  • someFunc1 与 createImpervaIP 函数几乎相似。 someFunc1 和 createImpervaIP () 之间唯一不同的是.. 选项变量中的路径:行。 someFunc1(在我的情况下实际上是 impervaGetSID 函数,它工作正常,fullResponse[1] 填充有效的会话 ID,它在 20-30 秒后出现。还有另一个函数 impervaFindIP () 与 impervaCreateIP 完全相同(只有方法从 POST 更改为GET).. 它有效!我已经在我的程序中创建了 Q 模块和延迟变量(我认为这很明显)。

标签: node.js rest promise asynccallback unexpectendoffile


【解决方案1】:

我要深入一点来回答你为什么你关于“完成比返回更快”的假设是错误的。

javascript的架构不允许在返回之前调用异步回调。

javascript 在单个线程上有一个堆栈,函数被压入堆栈,执行,然后弹出。你不能在一个堆栈上同时做两件事。

当 javascript 遇到异步操作时,它会通过 c++ libuv 库将该操作推送到另一个线程,然后当异步操作完成时,该操作在称为回调队列的东西上返回给 javascript。只有当堆栈为空时,事件队列中的东西才会被“事件循环”推送到堆栈中。因此返回值总是首先执行,因为触发异步函数的函数仍然占用 javascript 堆栈,直到遇到返回并将函数从堆栈中弹出,使其清晰并准备好接受回调队列中的内容。

尝试登录fullResponse,首先查看是否有fullResponse[1]

【讨论】:

  • 很好的解释。回答你的? - 是的,它确实。 fullResponse[0] 是一种大型 JSON 对象,其中一个字段是 statusCode(在我的情况下为 200),fullResponse[1] 为 .then(impervaCreateIP) 的 ''(空白)但相同的对象:如果我注释掉 .then(createImpervaIP) 行,则 fullResponse[0] 和 fullResponse[1] 将为 .then(someFunc1) 和 .then(someFunc3) 行/函数提供有效值,然后一切正常。 console.log(fullResponse) 显示了一个数组,其中 [0] 始终设置有一些 JSON 变量/值数据,[1] 设置有来自 Imperva REST/API 的响应
  • 1.您可以编辑您的答案以打印出fullResponse 吗?将 console.log(fullResponse) 放在 var results = ... 的正上方 2. 您将 qData['sid'] 传递给承诺链中的下一个函数,而不是 fullResponse 数据,因此您将无法获得它从参数那里。
  • 对不起,我从我的其他帖子中复制粘贴。是的,我发送的是 deferred.resolve(qData) 而不是 qData['sid'] (我之前发送的)。我会更正帖子。我还将把我得到的内容全部发布在 fullReponse 中
  • 尝试记录 fullResponse.body
  • 对于 fullResponse[1] 良好/具有有效值且 fullResponse[1] 为 BLANK/NULL 的情况,console.log(fullResponse.body) ... 将值显示为“未定义” .我还检查了整个 fullResponse 对象中的单词“body”,这就是我发现的: In fullResponse[0].req.ClientRequest["_hasBody"] -- 显示“true”,但这不是你想要的,对吧?
猜你喜欢
  • 1970-01-01
  • 2017-06-24
  • 2018-02-19
  • 2021-09-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-07-31
相关资源
最近更新 更多