Appium源码分析(6)-responses模块

Appium源码分析(4)-控制器模块文章中我们遗留了一个问题,是关于responses模块中的getResponseHandler函数的问题,索性今天我们直接来了解了解responses模块

加载模块

var logger = require('./logger.js').get('appium')
  , status = require('./status.js')
  , _ = require('underscore')
  , safely = require('./helpers').safely;

加载了4个模块,3个本地模块(logger,status,helpers)和一个核心工具模块(underscore)。本地模块我们后续再讲解,这个工具模块是做什么用的,我找到一篇文章讲解这个underscore,从这篇文章可以了解到这个模块主要提供了一些常用的函数,大概80个。

7个函数

reponses模块中包含7个函数,下面我们一步一步解释

getSessionId函数

//得到session的id号,每一个session都有一个独特的id用来标识
var getSessionId = function (req, response) {
  //判断传递过来的参数response是否初始化,如果已经初始化,sessionId的值就赋值为response的属性sessionId的值
  //否则赋值为undefined
  var sessionId = (typeof response === 'undefined') ? undefined : response.sessionId;
  //经过上面的赋值后,如果sessionId的值为undefined,那么就要进一步处理
  if (typeof sessionId === "undefined") {
    if (req.appium) {
      //如果req.appium初始化过,就将appium中的属性sessionId赋值给当前变量sessionId
      //需要注意的是后面的||null写法,如果req.appium.sessionId是没有定义的,那么会走到||后面,意思也是
      //给sessionId定义为null,如果不加||null,会发生什么呢?(sessionId=undefined)...
      sessionId = req.appium.sessionId || null;
    } else {
      //如果req.appium没有初始化,那么就直接将sessionId置为空
      sessionId = null;
    }
  }
  //因为我们要求返回的sessionId是一个字符串,那么我就要判断该类型是否正确,如果不正确,也需要置为null值
  if (typeof sessionId !== "string" && sessionId !== null) {
    sessionId = null;
  }
  return sessionId;
};

notImplementedInThisContext

//当我们调用的方法,并不存在的时候,会调用该方法,该方法一般是在设备端,执行查找或对某一个控件进行操作的。
var notImplementedInThisContext = function (req, res) {
  //首先打印提示信息
  logger.debug("Responding to client that a method is not implemented " +
              "in this context");
  safely(req, function () {
    //状态设置为501,并返回一个json字符串
    res.status(501).send({
      status: status.codes.UnknownError.code
    , sessionId: getSessionId(req)
    , value: {
      //提示信息消息体
        message: "Not implemented in this context, try switching " +
                 "into or out of a web view"
      }
    });
  });
};

上面的函数体内有2个地方需要理解:safely()和res.status(501).send()

函数意义
safelyhelpers.js模块中safely方法
res.status(501).send将response状态设置为501,然后发送一个消息

下面是safely方法的源码,也很简单,就是调用了嵌套的回调函数。

// Mainly used to wrap http response methods, or for cases where errors
// perdure the domain
var safely = function () {
  var args = new (Args)(arguments);
  var req = args.all[0];
  var fn = args.callback;
  try {
    fn();
  } catch (err) {
    logger.error('Unexpected error:', err.stack, getRequestContext(req));
  }
};

respondError

//返回错误信息
var respondError = exports.respondError = function (req, res, statusObj, value) {
  //设置错误信息的内容和状态码,因为message要求是字符串类型,code是整形类型
  var code = 1, message = "An unknown error occurred";
  var newValue = value;
  if (typeof statusObj === "string") {
    message = statusObj;
  } else if (typeof statusObj === "undefined") {
    message = "undefined status object";
  } else if (typeof statusObj === "number") {
    code = statusObj;
    message = status.getSummaryByCode(code);
  } else if (typeof statusObj.code !== "undefined") {
    code = statusObj.code;
    message = statusObj.summary;
  } else if (typeof statusObj.message !== "undefined") {
    message = statusObj.message;
  }
  //如果value的值是一个对象类型的值,需要从这个对象中解析出message属性
  //然后进行拼接组成一个json字符串,赋值给newValue,如果不是一个对象类型的值
  //直接组装成json字符串
  if (typeof newValue === "object") {
    if (newValue !== null && _.has(value, "message")) {
      // make sure this doesn't get obliterated
      value.origValue = value.message;
      message += " (Original error: " + value.message + ")";
    }
    newValue = _.extend({message: message}, value);
  } else {

    newValue = {message: message, origValue: value};
  }
  //拼接返回信息json字符串对象reponse
  var response = {status: code, value: newValue};
  //获取sessionId
  response.sessionId = getSessionId(req, response);
  logger.debug("Responding to client with error: " + JSON.stringify(response));
  //调用helpers.js模块的safely函数,就是调用里面的嵌套函数
  safely(req, function () {
    res.status(500).send(response);
  });
};

respondSuccess

var respondSuccess = exports.respondSuccess = function (req, res, value, sid) {
  var response = {status: status.codes.Success.code, value: value};
  response.sessionId = getSessionId(req, response) || sid;
  if (typeof response.value === "undefined") {
    response.value = '';
  }
  var printResponse = _.clone(response);
  var maxLen = 1000;
  if (printResponse.value !== null &&
      typeof printResponse.value.length !== "undefined" &&
      printResponse.value.length > maxLen) {
    printResponse.value = printResponse.value.slice(0, maxLen) + "...";
  }
  res.jsonResp = JSON.stringify(printResponse);
  logger.debug("Responding to client with success: " + res.jsonResp);
  safely(req, function () {
    res.status(200).send(response);
  });
};

这个函数我就不解释了,因为大致的方式都是一样的,都是先解析出打印的消息体,然后发送出去,只是这里面的response状态是200,因为是成功的。该方法调用的log信息,我们会经常见到。

getResponseHandler

exports.getResponseHandler = function (req, res) {
  //直接返回匿名函数
  return function (err, response) {
    //先判断response是否已经初始化,或者是否初始化为空
    if (typeof response === "undefined" || response === null) {
      //设置为空的json字符串
      response = {};
    }
    //判断错误的信息,符合如下条件的,直接抛出异常
    if (err !== null && typeof err !== "undefined" && typeof err.status !== 'undefined' && typeof err.value !== 'undefined') {
      throw new Error("Looks like you passed in a response object as the " +
                      "first param to getResponseHandler. Err is always the " +
                      "first param! Fix your codes!");
    } else if (err !== null && typeof err !== "undefined") {
      if (typeof err.name !== 'undefined') {
        if (err.name === 'NotImplementedError') {
          //如果错误的name值为NotImplementedError,就调用notImplementedInThisContext函数
          notImplementedInThisContext(req, res);
        } else if (err.name === "NotYetImplementedError") {
          //如果错误的name值为NotYetImplementedError,就调用notYetImplemented函数
          notYetImplemented(req, res);
        } else {
          //其他类型都调用respondError
          respondError(req, res, status.codes.UnknownError.code, err);
        }
      } else {
        var value = response.value;
        if (typeof value === "undefined") {
          value = '';
        }
        //如果错误类型name属性值为undefined,我们调用respondError的时候传入的参数为value值
        respondError(req, res, err.message, value);
      }
    } else {
      //如果错误信息为空或者未定义,我们需要根据状态码的不同,调用不同函数处理
      if (response.status === 0) {
        respondSuccess(req, res, response.value, response.sessionId);
      } else {
        respondError(req, res, response.status, response.value);
      }
    }
  };
};

终于到了我们真正要解释的函数了-getResponseHandler,从我上面的解释可以看出来,该函数是一个控制类的函数,所有的调用经过该函数处理后,会根据传入参数的不同,调用不同的函数,所以这个函数名字取为handler,以为回复处理器。

checkMissingParams

exports.checkMissingParams = function (req, res, params, strict) {
  //如果strict未定义,设置为false,说明strict为boolean类型的值
  if (typeof strict === "undefined") {
    strict = false;
  }
  var missingParamNames = [];
  //迭代params所有的元素,获取所有没有定义的或者值与strict相反的参数,添加到missingParamNames数组中
  _.each(params, function (param, paramName) {
    if (typeof param === "undefined" || (strict && !param)) {
      missingParamNames.push(paramName);
    }
  });
  if (missingParamNames.length > 0) {
    //将数组转化为json字符串
    var missingList = JSON.stringify(missingParamNames);
    logger.debug("Missing params for request: " + missingList);
    //response的状态为400,消息体为上面的json字符串的
    safely(req, function () {
      res.status(400).send("Missing parameters: " + missingList);
    });
    return false;
  } else {
    return true;
  }
};

上面的函数是找到为定义的参数或者为null的参数

notYetImplemented

//在getResponseHandler函数中我们看到当err.name为NotYetImplementedError时,会调用该函数
var notYetImplemented = exports.notYetImplemented = function (req, res) {
  //与notImplementedInThisContext类似,都是将response的状态设置为501,然后消息体不同
  logger.debug("Responding to client that a method is not implemented");
  safely(req, function () {
    res.status(501).send({
      status: status.codes.UnknownError.code
    , sessionId: getSessionId(req)
    , value: {
        message: "Not yet implemented. " +
               "Please help us: http://appium.io/get-involved.html"
      }
    });
  });
};

遗留问题

logger模块
status模块
helpers模块

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值