受欢迎的博客标签

微信小程序云开发(14)--小程序云函数-云函数调用http或https请求外部数据可选方法

Published

一、基础知识

Node.js中发起HTTP请求的各种方法如下,需从中选择一种发起调用

1.HTTP - 标准库

   首先是标准库中默认的HTTP模块。这个模块无需安装依赖外部即可使用,做到了真正的即插即用。缺点是与其他解决方案相比,用起来不是那么友好。

2.https

HTTPS与HTTP模块基本上都一样,唯一不同的地方就是HTTPS访问我们通常是需要证书,所以需要单独处理一下SSL证书

3.Request

Request是一个简化的http客户端。这个库比默认的http 模块更好用,多年来被开源社区作为开发首选。

与http 模块不同的是,你必须使用npm来安装它。

4.Axios

Axios是一个基于promise的HTTP客户端,可以用于浏览器和Node.js。在处理需要更复杂的事件链的代码时,使用Promises具有很大的优势。 编写异步代码可能会令人困惑,而Promises是这个问题的几种解决方案之一。必须使用npm来安装它。

5.Got

一个更轻量级的库,和Axios一样,Got也能同Promises一起很好的工作。如果你想要一个不像Request那样臃肿的轻量级的库,使用Got。必须使用npm来安装它。

6.request-promise

node.js 的request-promise模块。

二、安装模块依赖

目前依赖有两种安装方式可以选择:

(1)在开发者本地环境安装依赖,然后打包上传至云端

首先安装nodejs

cmd 打开云函数目录

 

输入

npm install --production

(2)直接在云端安装依赖

上传云函数时直接选择在云端安装依赖的上传方式

三、代码

request

https://developers.weixin.qq.com/community/develop/doc/0002cc8ccbc30073044701a4b51c00?jumpto=comment&commentid=000808c98cc040a60847b7c1e5b0

1.一个Node.js的模块——request

exports.main = (event, context) => {
  let result
  const request = require('request')
  return new Promise((resolve, reject) => {
    try {
      request(event.url, (err, resp, body) => {
        if (err) {
          return reject(err)
        }
        return resolve(body)
      })
    } catch (e) {
      return reject(err)
    }
  })
}

以下为https时才OK

 var request = require('request');
  request('http://www.iaspnetcore.com', function (error, response, body) {
    if (!error && response.statusCode == 200) {
      console.log(body) // 打印google首页
    }
    else
    {
      console.log("baidu error")
    }
  })

 

1.3测试通过的代码

/ 云函数入口文件
const cloud = require('wx-server-sdk')
var request = require('request')

cloud.init()

// 云函数入口函数
exports.main = async (event, context) => {
  // 这里获取到的 openId、 appId 和 unionId 是可信的,注意 unionId 仅在满足 unionId 获取条件时返回
  const wxContext = cloud.getWXContext()

 
  var appID = "wx20edd5723fb67***"
  var AppSecret = "bc31a88d18849a4bc91e9b50379c3**"
  var grant_type = "client_credential"
  var url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + appID + "&secret=" + AppSecret
  console.log(url)

  const apireq = url => new Promise((resolve, reject) => request.get(url, (err, response, body) => {
    if (err) {
      reject(err);
    } else {
      resolve(body);
    }
  }));

  let res = await apireq(url)
  console.log(res)
 

  return {
    event,
    openid: wxContext.OPENID,
    appid: wxContext.APPID,
    unionid: wxContext.UNIONID,
    
  }
}

1.4测试通过的代码

1.4.1 云函数

request

// 云函数入口文件
const cloud = require('wx-server-sdk')
const request = require('request')
//const got = require('got');
const apiUrl = 'http://www.isclab.org.cn/rsd/result_pred.php'

cloud.init()


// 云函数入口函数
exports.main = async (event, context) => {
  var isbn = event.isbn
  return new Promise((resolve, reject) => {
    request.get('http://isbn.szmesoft.com/ISBN/Query?ISBN=' + isbn, (error, response, body) => {
      if (error) {
        reject()
      } else {
        try {
          resolve(body)
        } catch (e) {
          reject()
        }
      }
    })
  })
}

1.4.2 调用云函数

//通过云函数获取博客列表
  onGetCloudBlogList: function () {
    // 调用云函数
    wx.cloud.callFunction({
      name: 'cloudBlogList',//这里填写云函数的名字
      data: {}, //这里是把参数e直接传给login函数处理
      success: res => {
        console.log('[云函数] [cloudBlogList] cloudBlogList: ', res)

      },
      fail: err => {
        console.error('[云函数] [cloudBlogList] 调用失败', err)
        wx.navigateTo({
          url: '../deployFunctions/deployFunctions',
        })
      }
    })
  },

 

 

2.用node.js 的request-promise模块发起请求

request-promise

// // 云函数入口文件
// const cloud = require('wx-server-sdk')

// cloud.init()
var rq = require('request-promise')
// 云函数入口函数
exports.main = async (event, context) => {
  console.log(event);
  var res = rq('https://api.douban.com/v2/book/isbn/' + event.isbn).then( html => {
    return html;
  }).catch( err => {
    console.log(err);
  })
  return res;
}

官方网站:https://github.com/request/request-promise#post-data-to-a-json-rest-api

demo:https://github.com/Iscrj/xiaochengxu/blob/135ed8dc4d4b6e793cb2bd8239464de94324f124/yun/cloudfunctions/bookinfo/index.js

2.2 node.js 的request-promise模块怎么发送带参数的POST请求

https://github.com/request/request-promise#post-data-to-a-json-rest-api

3.同步的http模块

node.js自带的http模块是异步获取网页内容的,不过我们可以到npm上去搜索同步的http模块。sync-request就是其中一种。

3.1 cloudfunctions/juhejokes先运行如下命令安装依赖

sync-request

npm install --save sync-request
npm install --save wx-server-sdk

3.2 

var request = require('sync-request')

var res = request('GET', 'http://m.haha.sogou.com/getMore/index?key=text&page=1')
var jokes = JSON.parse(res.getBody())

console.log(jokes)

demo:https://github.com/wangfengfly/jokes_wechat/blob/master/cloudfunctions/juhejokes/test.js

 

 

 
wenapi做了一个从数据库增删改查的项目

webapi:

1.创建项目:visual C# —> ASP.NET MVC 4 web应用程序 模板—>web api;

 

    

2.注册路由:

路由表中的每一个条目都包含一个路由模板。这个Web API默认的路由模版是"api/{controller}/{id}"。在这个模版中,“api”是一个文字式路径片段,而{controller}和{id}则是占位符变量。

当Web API框架接收一个HTTP请求时,它会试图根据路由表中的一个路由模板来匹配其URI。如果无路由匹配,客户端会接收到一个404(未找到)错误。

3.linq to sql连接数据库

1.建立数据库建表

2.在models文件夹里面新建linq to sql类文件

3.工具->连接到数据库

4.将要用的表拖入设计区

 

5.获取数据库Getway。"linq to sql class"文件名+Datacontext实例化这个对象,数据表就会映射到一个集合属性中,personDataDataContext db = new personDataDataContext();

6.增删改查

增:

public Boolean Post([FromBody]UserInfo userInfo)   {

personDataDataContext db = new personDataDataContext();

var s1 = new test2

{

UserName =userInfo.UserName,   Id=userInfo.Id,   Age=userInfo.Age

};

if (db.test2.SingleOrDefault<test2>(s => s.Id == userInfo.Id) == null)

{

db.test2.InsertOnSubmit(s1);

db.SubmitChanges();

return true;

}   else {

return false;

}   }

删:

public bool Delete(int id)

{

personDataDataContext db = new personDataDataContext();

var deleteperson = db.test2.SingleOrDefault<test2>(s => s.Id == id);

if (deleteperson == null)

{

return false;

}   else {

db.test2.DeleteOnSubmit(deleteperson);

db.SubmitChanges();

return true;

}     }

改:

public Boolean Put(int id, [FromBody]UserInfo userInfo)

{

personDataDataContext db = new personDataDataContext();

var editperson = db.test2.SingleOrDefault<test2>(s => s.Id == userInfo.Id);

if (editperson == null)

{

return false;

}   else {

editperson.Age = userInfo.Age;

editperson.UserName = userInfo.UserName;

db.SubmitChanges();

return true;

}

查:

public IEnumerable<test2> Get()

{

personDataDataContext db = new personDataDataContext();

var query = from s in db.test2  

orderby s.UserName

select s;

return query;

}

// GET api/values/5

public string Get(int id)

{

return "value";

}

这里我新建了一个userinfo类

   public class UserInfo   {     public string UserName { get; set; }     public int Id { get; set; }     public int Age { get; set; }   }

用来接收前端页面ajax请求中的data数据,s => s.Id == userInfo.Id是lamda表达式创建委托方法意思是在db.test2的person集合中查找某个person的Id与userinfo接收到的id相等的person对象

 

前端页面部分

@{     Layout = null; }

<!DOCTYPE html>

<html>

<head>

    <meta name="viewport" content="width=device-width" />

    <title>index</title>

    <link href="~/CSS/bootstrap.css" rel="stylesheet" />

    <script src="~/Scripts/jquery-1.11.3.min.js"></script>

    <script src="~/Scripts/bootstrap.js"></script>

    <script src="~/Scripts/sweetalert-dev.js"></script>    

    <script src="~/Scripts/sweetalert.min.js"></script>    

    <script src="~/Scripts/table.js"></script>    

    <link href="~/CSS/sweetalert.css" rel="stylesheet" />

    <link href="~/CSS/table.css" rel="stylesheet" />

</head>

<body>

    <div>

        <input type="button" data-toggle="modal" href="#modal-login" class="btn btn-success btn-primary btn-lg btn-block" value="增加" />

    </div>

    <table id="table" class="table table-hover table-bordered">

        <thead>

            <tr class="active">

                <th>用户名</th>

                <th>工号</th>

                <th>年龄</th>

                <th>操作</th>

            </tr>

        </thead>

       <tbody></tbody>

    </table>

    <!---------------------------------------------模态框------------------------------------------------>

    <div id="modal-login" class="modal fade">

        <!--半透明遮罩-->

        <div class="modal-dialog">

            <!--宽、定位-->

            <div class="modal-content">

                <!--背景色、边框、阴影-->

                <div class="modal-header">

                    <span data-dismiss="modal" class="close">&times;</span>

                    <h3 class="modal-title">用户信息添加</h3>

                </div>

                <div class="modal-body">

                    <form>

                        <div class="form-group">

                            <label for="uname">用户名:</label>

                            <input class="form-control" id="uname" type="text" />

                        </div>

                        <div class="form-group">

                            <label for="uid">工号:</label>

                            <input class="form-control" id="uid" type="text" />

                        </div>

                        <div class="form-group">

                            <label for="upwd">年龄:</label>

                            <input class="form-control" id="uage" type="text" />

                        </div>

                    </form>

                </div>

                <div class="modal-footer">

                    <input id="submitData" class="btn btn-success" type="button" value="提交" />

                    <input id="cancel" data-dismiss="modal" class="btn btn-danger" type="button" value="取消" />

                </div>

            </div>

        </div>

    </div>

</body>

</html>

 

 

js文件:

$(function () {

    $.ajax({

        type: "GET",

        url: "/api/Values",

        data: {},

        success: function (data) {

            for (var i = 0; i < data.length; i++) {

                var $info = $("<tr><td>" + data[i].UserName + "</td><td>" + data[i].Id + "</td><td>" + data[i].Age + "</td><td><input type='button' class='btn btn-warning btn-lg' id='btnPutUserInfo' data-toggle='modal' href='#modal-login' href='#modal-login' value='修改' /><input type='button' class='btn btn-danger btn-lg delete' value='删除'/></td></tr>");

                $("#table>tbody").append($info);

            }

        }

    })

    //绑定post按钮点击事件 $("#submitData").click(function (e) {

        if (e.target.value !== '修改') { console.log(e.target.value !== '修改'); console.log(e.target.value)

            var uname = document.getElementById("uname");

            var uid = document.getElementById("uid");

            var uage = document.getElementById("uage");

            if (uid.value === null) { return false }

            $.ajax({

                type: "POST",

                url: "/api/Values",

                data: { "Id": uid.value, "Age": uage.value, "UserName": uname.value },

                success: function (data) {

                    if (data == true) {

                        swal("添加成功!","", "success");

                    } else {

                        swal("添加失败!","","error");

                    }                     $(".confirm").click(function () { window.location.reload(); })

                }

            })

        }

    })

    //绑定修改和删除事件 $("table").on('click', function (e) {

        if (e.target.value == '删除') { swal({

                title: "您确定要删除吗?",  text: "您确定要删除这条数据?",  type: "warning",

                showCancelButton: true,

                closeOnConfirm: false,

                confirmButtonText: "是的,我要删除", confirmButtonColor: "#ec6c62"

            }, function() {

                $.ajax({

                    type: "DELETE",

                    url: "/api/Values/" + e.target.parentNode.parentNode.firstChild.nextSibling.innerHTML,

                    data: {},

                }).done(function (data) {

                    swal("操作成功!", "已成功删除数据!", "success");

                    $(".confirm").click(function () { window.location.reload(); })

                }).error(function(data) {

                    swal("OMG", "删除操作失败了!", "error");

                    $(".confirm").click(function () { window.location.reload(); })

                });             });

        } else if (e.target.value == '修改') {

try { $("#submitData")[0].id = "submitChange" }

                catch (e) { };

                $("form div:nth-child(2)").remove();

                $("#submitChange")[0].value = '修改'; var uname = document.getElementById("uname");

                var uage = document.getElementById("uage");

                var age = e.target.parentNode.previousSibling;

                var id = age.previousSibling;

                var name = id.previousSibling;

                uage.value = age.innerHTML//年龄 uname.value = name.innerHTML//用户名       $("h3")[0].innerHTML = "用户信息修改"

                $("#submitChange").click(function () {

                    console.log(id.innerHTML);

                    $.ajax({

                        type: "PUT",

                        url: "/api/Values/" + id.innerHTML,

                        data: { "Id": id.innerHTML, "Age": uage.value, "UserName": uname.value },

                        success: function (data) {

                            if (data == true) {

                                swal("修改成功!","", "success");

                            } else {

                                swal("修改失败!","", "error");

                            }

                            $(".confirm").click(function () { window.location.reload(); })

                        }

                    })

                })

                $("#cancel").click(function () { window.location.reload();  })         }     }) })

前端截图:

 

      

css对表格做了些样式处理我就不贴出来了,这里我用了一个弹窗的jquery插件叫sweetalert.js所有里面有swal这个方法调用。说一下前端页面我主要遇到的问题:

前端我在页面加载后执行Get方法获取数据库中的所有记录。通过遍历拼接字符串加载表格和按钮。

1.在对按钮绑定事件的时候我发现修改和删除按钮绑定的事件不能被触发可能是由于这两个按钮是生成的按钮不能绑定click事件,于是我先绑定原先的table,再用e.target获取事件对象,对事件对象进行判断,执行修改或删除命令。

2.在修改时因为我添加事件也使用了之前那个模态框导致我做修改的时候程序是走到了绑定添加的事件里面的,为了将这两个事件区别开,我在put方法下先修改了提交按钮的id,在绑定这个新的id的按钮事件来解决这个问题。

三、参考资料

Node.js中5种发起HTTP请求的方法

https://segmentfault.com/a/1190000010698468