How to use 3rd party method that takes callback in

2019-08-28 11:58发布

问题:

I need some help here... I am using a 3rd party method which takes callback in it ... so now if i want to use that in WDIO i need to wrap that method inside promise ... So i did the following:

post(env, userAccount, canonical, isItQuery){
    let options = { ..... };
    return new Promise(function(resolve, reject){
        request.post(options,function(error, response){
            logger.info('In to the callback of request post');
            if(!error){
                resolve(response);
            }
            else{
                reject(error);
            }                
        });
    });
}

And i tried calling this method inside stepDefinition like this:

      rm.post(env,userAccountID,payloadName,true).then(function(resp) {
        console.log('Response: ' + resp);
    })
    .catch(function(error){
        console.log("ERROR: " + error);
    })

During the execution the script is not waiting for the response from request.post method ... and execution is getting completed without its response ... Please help me how i can make this work ...

I tried the same using request-promise npm-module which returns promise instead of taking callback and getting the same issue:

Here is the sample code:

import {defineSupportCode} from 'cucumber';
import request from 'request-promise';
import config from 'config';
import fs from 'fs';
require('request-promise').debug = true;

defineSupportCode(function({Given, When, Then}){
    Given(/^Run the "([^"]*)" with user_session of "([^"]*)"$/, (canonical, user_session) => {

        .......
        .......
        const payload = fs.readFileSync(path,{encoding:'utf8'});

        let options = {
            ...........
            ...........
        };

        request(options)
        .then(function ($) {
              console.log($);
         })
        .catch(function (err) {
       console.log('error');
         });
    });
});

I am using wdioRunner with sync:true. I am using cucumber framework.

Thank you!!

回答1:

Ok.. With some help i was able to fix the issue. So wdioRunner(with sync:true) runs every command synchronous. So now if you want to use an async method which takes callback then you need to use browser.call.

http://webdriver.io/api/utility/call.html#Usage

so this is how the post method should be:

post(env, userAccount, canonical, isItQuery){
let options = { ..... };
browser.call(() => {
    return new Promise(function(resolve, reject){
        request.post(options,function(error, response, resp){
            console.log('Inside the callback!!!!!');
            jsonResponse = resp;
            if(!error){
                console.log('NO Error: ' + resp);                    
                resolve(resp);

            }
            else{
                console.log('Error: ' + error);
                reject(error);
            }
    });
});
}


回答2:

You are missing what to return from the promise.

You need a response just try returning it .

You can also return a array with status code and response etc.

Install request-promise npm install --save request-promise

var rp = require('request-promise');
var cheerio = require('cheerio'); 
var options = {
        uri: 'http://www.google.com',
                  transform: function (body) {
                     return cheerio.load(body);
                   }
               }; 
 rp(options)
     .then(function ($) {
           console.log($);
      })
     .catch(function (err) {
    console.log('error');
      });

The response body looks like

{ [Function: initialize]
  fn:
   initialize {
     constructor: [Circular],
     _originalRoot:
      { type: 'root',
        name: 'root',
        namespace: 'http://www.w3.org/1999/xhtml',
        attribs: {},
        'x-attribsNamespace': {},
        'x-attribsPrefix': {},
        children: [Array],
        parent: null,
        prev: null,
        next: null } },
  load: [Function],
  html: [Function],
  xml: [Function],
  text: [Function],
  parseHTML: [Function],
  root: [Function],
  contains: [Function],
  merge: [Function],
  _root:
   { type: 'root',
     name: 'root',
     namespace: 'http://www.w3.org/1999/xhtml',
     attribs: {},
     'x-attribsNamespace': {},
     'x-attribsPrefix': {},
     children: [ [Object], [Object] ],
     parent: null,
     prev: null,
     next: null },
  _options:
   { withDomLvl1: true,
     normalizeWhitespace: false,
     xml: false,
     decodeEntities: true } }