Function works, but fails when util.promisify() us

2019-06-15 13:16发布

问题:

I have some code using node-bing-api. It's err-first and works perfectly, but I'd like to convert it to using Promises (and await).

I'm using node 8, and util.promisify. In the code below, Bing.web is the regular err-first code, and searchBing is the promisified version.

var findParentDir = require('find-parent-dir'),
    configDir = findParentDir.sync(__dirname, 'config.js'),
    config = require(configDir+'config.js'),
    util = require('util'),
    log = console.log.bind(console),
    Bing = require('node-bing-api')({ accKey: config.cognitiveServices.bingSearch }),
    searchBing = util.promisify(Bing.web);

var start = async function(){
    // This fails
    // var searchResultsRaw = await searchBing('windows', {top: 5})
    // log(searchResultsRaw)

    // This works
    Bing.web('windows', {top: 5}, function(err, searchResultsRaw){
        log(searchResultsRaw)
    })
};

start();

The promisified version fails with:

(node:1752) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 2): TypeError: this.searchVertical is not a function

This is an error inside node-bing-api. But shouldn't util.promisify be passing the options on to the real bing.web seamlessly, using the same arguments as the original function?

Why won't this function work when promisified?

Note I can make my own promisifed version - which works - but I'd rather not create extra code:

var searchBing = function(){
  return new Promise(function(resolve, reject) {
    Bing.web('windows', {top: 5}, function(err, searchResults){
      if ( err ) {
        reject(err)
        return
      }
      resolve(searchResults)
    })
  })
}

回答1:

It's probably missing context: the function Bing.web is using this in its body, which is not bound to Bing when using util.promisify.

You need to explicitly bind it via:

searchBing = util.promisify(Bing.web.bind(Bing));