【问题标题】:Using Async/Await in WATSON Nodejs SDK在 WATSON Nodejs SDK 中使用 Async/Await
【发布时间】:2018-09-10 03:48:35
【问题描述】:

我正在使用 WATSON API 构建一个聊天机器人,在其中我使用 async/await 方法从 MongoDB 获取数据并获得结果,然后将其发送回用户。

函数 artpromise 是从 mongo DB 收集数据的 Promise。函数 randomartist 是一个从数据库中获取 3 个随机文档的函数。但是,WATSON BLUEMX Cloud 服务支持不支持异步方法的 6.1.3 的 Nodejs SDK。有什么方法可以更新 Blumix 上的 SDK 版本,还是我应该使用不同的方法从服务器获取数据?

let getConversationResponse = (message, context) => {
  let payload = {
    workspace_id: process.env.WORKSPACE_ID,
    context: context || {},
    input: message || {}
  };

  payload = preProcess(payload);

  return new Promise((resolved, rejected) => {
    // Send the input to the conversation service
    conversation.message(payload, async function(err, data) {
      if (err) {
        rejected(err);
      }
      else{
          if(data.context.type == 'ask'){
              let artist = data.context.name;
              let result = await artpromise(artist);
              console.log(result);
              data.context.name  = result[0].name;
              data.context.nationality = result[0].nationality;
              data.context.birth = result[0].years;
              data.context.url = result[0].art_link;
              data.output.text = data.context.name+' is a '+data.context.nationality+' artist  from '+data.context.birth+'. Check out a painting at '+data.context.url;
          }

          else if(data.context.type == 'random_artist'){
              let result = await randomArtist();
              console.log(result);
              data.output.text = 'Let\'s find some random artists for you! \n'+result;
          }
        let processed = postProcess(data);
        if(processed){
          // return 값이 Promise 일 경우
          if(typeof processed.then === 'function'){
            processed.then(data => {
              resolved(data);
            }).catch(err => {
              rejected(err);
            })
          }
          // return 값이 변경된 data일 경우
          else{
            resolved(processed);
          }
        }
        else{
          // return 값이 없을 경우
          resolved(data);
        }
      }
    });
  })
} 

【问题讨论】:

    标签: node.js ibm-cloud watson watson-conversation


    【解决方案1】:

    使用 Node 的 util.promisify() 实用程序,您可以将回调样式的函数转换为基于 Promise 的函数。

    getConversationResponse-函数之外的某个地方,将它分配给一个局部变量:

    const util = require('util');
    const messagePromise = util.promisify(conversation.message);
    

    并改用该功能。这样的事情应该可以工作:

    const util = require('util');
    const messagePromise = util.promisify(conversation.message);
    
    let getConversationResponse = async (message, context) => {
      let payload = preprocess({
        workspace_id: process.env.WORKSPACE_ID,
        context: context || {},
        input: message || {}
      });
    
      let data = await messagePromise(payload);
      if (data.context.type == 'ask') {
        let artist = data.context.name;
        let result = await artpromise(artist);
        console.log(result)
        data.context.name  = result[0].name;
        data.context.nationality = result[0].nationality;
        data.context.birth = result[0].years;
        data.context.url = result[0].art_link;
        data.output.text = data.context.name+' is a '+data.context.nationality+' artist  from '+data.context.birth+'. Check out a painting at '+data.context.url;
      } else if (data.context.type == 'random_artist'){
        let result = await randomArtist();
        console.log(result);
        data.output.text = 'Let\'s find some random artists for you! \n'+result;
      }
    
      return postProcess(data) || data;
    };
    

    注意,如果postProcess 的返回值为falsy,则它会改为返回data 变量。此外,async 函数总是返回一个 Promise,所以要调用这个函数,你需要这样做:

    getConversationResponse(message, context).then((data) => {
      // Do something with the data
    }).catch((e) => {
      // Handle the error!
    });
    

    或者如果你从另一个异步函数调用它:

    let data = await getConversationResponse(message, context);
    

    或者如果您需要专门捕获调用异步函数中的错误:

    try {
      let data = await getConversationResponse(message, context);
    } catch (e) {
      // Handle error
    }
    

    就像常规的同步代码一样,函数调用链中抛出的任何错误都会“涓涓细流”到最顶层的被调用者。如果您对此感到困惑,我建议您阅读错误处理。

    如果您想在整个代码中以基于异步 Promise 的方式使用 Watson API,编写一个小型包装库并直接使用它可能是可行的。


    仅 Promise 的实现:

    const util = require('util');
    const messagePromise = util.promisify(conversation.message);
    
    let getConversationResponse = (message, context) => {
      let payload = preprocess({
        workspace_id: process.env.WORKSPACE_ID,
        context: context || {},
        input: message || {}
      });
    
      return messagePromise(payload).then((data) => {
        if (data.context.type == 'ask') {
          let artist = data.context.name;
          return artpromise(artist).then((result) => {
            data.context.name  = result[0].name;
            data.context.nationality = result[0].nationality;
            data.context.birth = result[0].years;
            data.context.url = result[0].art_link;
            data.output.text = data.context.name+' is a '+data.context.nationality+' artist  from '+data.context.birth+'. Check out a painting at '+data.context.url;
            return data;
          });
        } else if (data.context.type == 'random_artist') {
          return randomArtist().then((result) => {
            data.output.text = 'Let\'s find some random artists for you! \n' + result;
            return data;
          });
        }
      }).then((data) => {
        return postProcess(data) || data;
      });
    };
    

    调用它与async/await 实现完全相同。

    【讨论】:

    • 再次感谢 Svenslunganka!但是我也在考虑安装在 Nodejs 7.6 之前使用的 asyncawait 包,你认为这也可以吗?
    • 哦,我完全误解了你,我以为你的意思是他们只支持他们自己的SDK的特定版本。 Node.js 是运行时,而不是 SDK。如果你愿意,我可以提供一个纯粹基于 Promise 的实现,因为 Promise 在 Node 6.1.3 中可用。
    • @Maeror 我做了一个快速检查,根据their docs 他们支持所有版本的 Node.js。您只需在您的package.json 中将engines.node 设置为特定版本(例如最新的9.10.1)。我的答案中的代码应该可以正常工作。
    • 我在 bluemix 服务器上尝试过,但仍然无法正常工作...几个月来一直在尝试上传...如果您不介意可以帮助我提供承诺代码,允许它适用于 nodejs 6??
    • @Maeror 我通常不会竭尽全力提供帮助,但是由于您已经被这个问题困扰了几天,所以我添加了一个仅承诺的实现到答案。试一试,如果有效,花点时间研究一下,试着了解发生了什么。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-06-13
    • 2022-11-23
    • 2021-10-05
    • 2021-06-15
    • 1970-01-01
    • 2019-01-03
    • 1970-01-01
    相关资源
    最近更新 更多