无法实现基于回调的函数

时间:2019-08-21 18:32:13

标签: javascript node.js promise node-promisify

我想使用astro-js库,其中文档中的典型调用如下:

const aztroJs = require("aztro-js");

//Get all horoscope i.e. today's, yesterday's and tomorrow's horoscope
aztroJs.getAllHoroscope(sign, function(res) {
   console.log(res);
});

出于几个原因,我想使用异步/等待风格并利用try / catch来使用它。所以我尝试了这样的承诺:

const aztroJs = require("aztro-js");
const {promisify} = require('util');
const getAllHoroscopeAsync = promisify(aztroJs.getAllHoroscope);

async function handle() {
  let result, sign = 'libra';
  try {
    result = await getAllHoroscopeAsync(sign);
  }
  catch (err) {
    console.log(err);
  }
  console.log("Result: " + result);
}

但是,当我记录结果时,它是未定义的。我知道该调用有效,因为该库通过console.log自动记录了响应,并且在日志中看到了正确的响应。

如何在此通话中“等待”? (即使不是“可承诺的”,也可以通过其他方式)

3 个答案:

答案 0 :(得分:1)

您可以将getAllHoroscopeAsync更改为Promise函数

示例:

const getAllHoroscopeAsync = (sign) => 
    new Promise(resolve => 
            aztroJs.getAllHoroscope(sign, (res) => resolve(res)));

答案 1 :(得分:1)

util.promisify()期望回调函数接受两个参数,第一个是错误,在没有错误时必须为null,在有错误时必须为null,第二个是值(如果没有错误)。仅当回调遵循特定规则时,它才能正确分配函数。

要解决此问题,您将不得不手动使功能分散。

// manually promisify
aztroJs.getAllHoroscopePromise = function(sign) {
    return new Promise(resolve => {
        aztroJs.getAllHoroscope(sign, function(data) {
            resolve(data);
        });
    });
};

// usage
aztroJs.getAllHoroscopePromise(sign).then(results => {
    console.log(results);
});

请注意,返回数据的异步函数没有返回错误的方法是不寻常的,因此在这方面,aztroJs.getAllHoroscope()接口似乎有点可疑。

实际上,如果您查看code for this function,可以看到它正在使用request()库发出网络请求,然后在出现错误时尝试在异步回调中throw 。这是一个完全有缺陷的设计,因为您(作为调用者)无法捕获异步引发的异常。因此,此软件包没有合理的方法来传递回错误。设计不当。

答案 2 :(得分:1)

尝试自定义承诺功能

aztroJs.getAllHoroscope[util.promisify.custom] = (sign) => {
  return new Promise((resolve, reject) => {
    aztroJs.getAllHoroscope(sign, resolve);
  });
};

const getAllHoroscopeAsync = util.promisify(aztroJs.getAllHoroscope);