Node.js学习笔记(五)

其他

异步编程
  • 函数也是一种数据类型,既可以当做参数进行传递,也可以当做方法返回值
  • 一般情况下,把函数作为参数的目的就是为了获取函数内部的异步操作结果
  • JavaScript 事件循环、单线程
  • 回调函数
    • console.log(‘1’)
      setTimeout(function(){
      console.log(‘2’)
      },0)
      console.log(‘3’)
      # 执行结果:任何时候都是1,3,2,因为Js的单线程、事件循环机制
  • 不成立的情况:
    • function add(x, y){
      console.log(1)
      setTimeout(function(){
      console.log(2)
      var ret = x + y
      return ret
      },1000)
      console.log(3)
      // 到这里执行结束,不会等到前面的定时器,所以直接就返回默认值undefined
      }
      console.log(add(10,20)) // => undefined
  • 不成立的情况
    • function add(x, y){
      var ret
      console.log(1)
      setTimeout(function(){
      console.log(2)
      ret = x + y
      },1000)
      console.log(3)
      return ret
      }
      console.log(add(10,20)) // => undefined
  • 注意:凡是需要得到一个函数内部异步操作的结果,setTimeout,readFile,writeFile
  • 回调函数
    这是javascript编程的一大特色,异步编程。
    • function add(x, y, callback){
      // callback 就是回调函数
      // var x = 10
      // var y = 20
      // var callback = function(a){}
      console.log(1)
      setTimeout(function(){
      var ret = x + y
      callback(ret)
      },1000)
      }
      add(10, 20, function(a){
      // a才是我们得到的结果
      })
find/findIndex

find接收一个方法作为参数,方法内部返回一个条件,find会遍历所有的元素,执行你给定的带有条件返回值的函数,符合该条件的元素作为find方法的返回值,如果遍历结束还没有找到符合条件的元素,则范湖iundefined

8. MongoDB

8.1 关系型数据库和非关系型数据库

表就是关系或者说表与表时间存在关系。

  • 所有的关系型数据库都需要通过sql语言来操作
  • 所有的关系型数据库在操作之前都需要设计表结构
  • 而且数据表还支持约束
    • 唯一的
    • 主键
    • 默认值
    • 非空
  • 非关系想数据库非常的灵活
  • 有的非关系型数据库就是key-value对
  • 但是MongoDB是长得最像关系型数据库的非关系型数据库
    • 数据库》数据库
    • 数据库》集合(数组)
    • 表记录》(文档对象)
  • MongoDB是不需要设计表结构
  • 也就是说可以任意的往里面存数据,没有结构性这么一说
8.2 安装
8.3 启动和关闭数据库

启动:

# mongodb 默认使用执行 mongod 命令所处盘符根目录下的/data/db作为自己的数据存储目录
# 所以在第一次执行该命令之前先自己手动新建一个 /data/db
mongod

如果想要修改默认的数据库存储目录,可以:

mongod --dbpath=数据存储目录路径

停止:

在开启服务的控制台,直接Ctrl+c即可停止。
或者直接关闭开启服务的控制台也可以。
8.4 连接和退出数据库

连接:

# 该命令默认链接本机的 MongoDB服务
mongo

退出:

# 在链接状态输入 exit 退出连接
exit
8.5 基本命令
  • show dbs
    • 查看显示所有数据库
  • db
    • 查看当前操作的数据库
  • use 数据库名称
    • 切换到指定的数据(如果没有会新建)
  • 插入数据
    • db.students.insertOne({“name”:”jack”})
  • 显示当前db 的所有集合
    • show collections
  • 查询当前db的所有数据
    • db.students.find()
8.6 在Node中如何操作MongoDB数据库

使用官方的mongodb包来操作

http://mongodb.github.io/node-mongodb-native

使用第三方mongoose来操作MongoDB数据库

第三方包:mongoose基于MongoDB官方的mongodb包再一次做了封装。

  • 网址 https://mongoosejs.com/
  • 官方指南:https://mongoosejs.com/docs/guide.html
  • 官方API文档:https://mongoosejs.com/docs/api.html
  • 初始化项目
    • cnpm init -y
  • 安装mongoose
    • cnpm i mongoose
  • 连接操作
    • # 引包
      const mongoose = require(‘mongoose’);
      # 连接 MongoDB 数据库
      # 指定连接的数据库不需要存在,当你插入第一条数据之后就会自动被创建出来
      mongoose.connect(‘mongodb://localhost/test’);
      # 创建一个模型,就是在设计数据库
      # MongoDB是动态的,非常灵活,只需要在代码中设计你的数据库就可以了
      # mongoose这个包可以让你的设计编写过程变得非常简单
      const Cat = mongoose.model(‘Cat’, { name: String });
      # 实例化一个Cat
      const kitty = new Cat({ name: ‘Zildjian’ });
      # 持久化保持kitty实例
      kitty.save().then(() => console.log(‘meow’));
8.7 MongoDB数据库的基本概念
  • 数据库(可以有多个数据库)
  • 集合(一个数据库中可以有多个集合)
  • 文档(一个集合中可以有多个文档(表记录))
  • 文档结构很灵活,没有任何限制
  • MongoDB非常灵活,不需要像 MySQL一样先创建数据库、表、设计表结构
  • 在这里只需要:当你需要插入数据的时候,只需要指定往哪个数据库的哪个集合操作就可以了
  • 一起都由MongoDB来自动完成建库建表
    {
    qq:{
    users:[
    {name: ‘张三’, age: 12},
    {}
    ],
    products:[]
    },
    taobao:{},
    baidu:{}
    }
8.8 官方指南

设计Scheme发布Model

var mongoose = require('mongoose')
var Schema = mongoose.Schema
// 1. 连接数据库,连接本地的itcast数据库,该数据库可以不存在,自动创建
mongoose.connect('mongodb://localhost/itcast');

// 2. 设计集合结构(表结构)
// 字段名称就是表结构中的属性名称
// 约束的目的是为了保证数据的完整性,不要有脏数据
var userSchema = new Schema({
    username: {
        type: String,
        required: true
    },
    password: {
        type: String,
        required: true
    },
    email: {
        type: String
    }
});

// 3. 将文档结构发布为模型
// mongoose.model方法就是用来将一个架构发布为model
// 第一个参数:传入一个大写名词单数字符串用来表示你的数据库名称
// 例如这里的User最终会变为users集合名称
// 第二个参数:架构Schema
// 返回值:模型构造函数
var User = mongoose.model('User',userSchema)

// 4. 当我们有了一个模型构造函数之后,就可以使用这个构造函数对User集合中的数据为所欲为了
module.exports =User

增加数据

var admin = new User({
    username: 'admin',
    password: '123345',
    email: '[email protected]'
})

admin.save(function(err,ret){
    if(err){
        console.log('保存失败');
    }else{
        console.log('保存成功')
        console.log(ret)
    }
})

查询

查询所有

User.find(function(err,ret){
    if(err){
        console.log('查询失败')
    }else{
        console.log(ret)
    }
})

按条件查询所有

User.find({
    username: '张三'
},function(err,ret){
    if(err){
        console.log('查询失败')
    }else{
        console.log(ret)
    }
})

按条件查询单个数据

User.findOne({
    username: 'admin',
    password: 222
},function(err,ret){
    if(err){
        console.log('查询失败')
    }else{
        console.log(ret)
    }
})

删除数据

User.remove({
    username: 'admin'
},function(err,ret){
    if(err){
        console.log('删除失败')
    }else{
        console.log('删除成功')
    }
})
# 根据条件删除一个
Model.findOneAndRemove(conditions,[options],[callback])
# 根据 id 删除一个
Model.findByIdAndRemove(id,[options],[callback])

更新数据

# 根据条件更新所有
Model.update(conditions,doc,[options],[callback])
# 根据指定的条件更新一个
Model.findOneAndUpdate([conditions],[update],[options],[callback])
# 根据id
User.findByIdAndUpdate('5b78008cfd7edbd6beda079c',{
    password: '123'
},function(err,ret){
    if(err){
        console.log('更新失败')
    }else{
        console.log('更新成功')
    }
})
8.9 nodejs连接mysql
  1. 安装

使用在npmjs.com中搜索即可

npm i mysql
  1. 使用

    var mysql = require(‘mysql’);

    // 创建连接
    var connection = mysql.createConnection({
    host : ‘localhost’,
    user : ‘me’,
    password : ‘secret’,
    database : ‘my_db’
    });
    // 连接数据库
    connection.connect();
    // 执行数据操作
    // connection.query(‘sql 语句’)
    connection.query(‘SELECT 1 + 1 AS solution’, function (error, results, fields) {
    if (error) throw error;
    console.log(‘The solution is: ‘, results[0].solution);
    });
    // 关闭连接
    connection.end();

9. Promise

9.1 callback hell:(回调地狱)

无法保证顺序的代码:

var fs = require('fs')

fs.readFile('./data/a.txt','utf8',function(err,data){
    if(err){
        // 抛出异常
        //     1. 阻止程序的执行
        //     2. 把错误消息打印到控制台
        throw err
    }
    console.log(data)
});

fs.readFile('./data/b.txt','utf8',function(err,data){
    if(err){
        throw err
    }
    console.log(data)
});

fs.readFile('./data/c.txt','utf8',function(err,data){
    if(err){
        throw err
    }
    console.log(data)
});

通过回调嵌套的方式来保证顺序:

var fs = require('fs')

fs.readFile('./data/a.txt','utf8',function(err,data){
    if(err){
        // 抛出异常
        //     1. 阻止程序的执行
        //     2. 把错误消息打印到控制台
        throw err
    }
    console.log(data)
    fs.readFile('./data/b.txt','utf8',function(err,data){
        if(err){
            throw err
        }
        console.log(data)
        fs.readFile('./data/c.txt','utf8',function(err,data){
            if(err){
                throw err
            }
            console.log(data)
        });
    });
});

为了解决以上的编码方式带来的问题(对调地狱嵌套),所有es6中新增了一个API,promise

9.2 Promise

Promise是一个构造函数

Promise容器,容器中存放了一个异步任务

Promise本身不是异步,但是内部往往都是封装了一个异步任务

Promise基本语法:

var fs = require('fs')
// 创建 Promise容器
// 1. 给别人一个承诺 
//      Promise 容器一旦创建,就开始执行里面的代码

var p1 = new Promise(function(resolve,reject){
    fs.readFile('./data/a.txt', 'utf8', function(err,data){
        if(err){
            // 失败了,承诺容器中的任务失败了
            // console.log(err)
            // 把容器的Pending状态变为Rejected
            // 调用reject就相当于调用了then的第二个回调函数
            reject(err)
        }else{
            // 承诺容器中的任务成功了
            // console.log(data)
            // 把容器的Pending状态改为成功 Resolved
            // 也就是说这里调用的resolve方法实际上就是then方法传递的那个function
            resolve(data)
        }
    });
})
var p2 = new Promise(function(resolve,reject){
    fs.readFile('./data/b.txt', 'utf8', function(err,data){
        if(err){
            reject(err)
        }else{
            resolve(data)
        }
    });
})
// p1 就是那个承诺
// 当 P1 成功了,然后then做指定的操作
// then方法接收的function就是容器中的resolve函数
p1.then(function(data){
    console.log(data) //这是p1返回的数据
    // 当p1读取成功时候
    // 当前函数中return的结果就可以在后面的then中的function接收到
    // 当你return 123 后面就接收到123,return什么后面就接收到的什么
    // 真正有用的是:我们可以return一个promise对象
    // 当return一个Promise对象的时候,后续的then中的方法的第一个参数会作为p2的返回值
    return p2
},function(err){
    console.log('读取文件失败了'+err)
})
.then(function(data){
    console.log(data) // 这个方法就是作为p2的resolve
})
9.3 封装Promise版本的readFile
var fs = require('fs')

function pReadFile(filePath){
    return new Promise(function(resolve,reject){
        fs.readFile(filePath, 'utf8', function(err,data){
            if(err){
                reject(err)
            }else{
                resolve(data)
            }
        });
    }) 
}

pReadFile('./data/a.txt').then(function(data){
    console.log(data)
    return pReadFile('./data/b.txt')
}).then(function(data){
    console.log(data)
    return pReadFile('./data/c.txt')
}).then(function(data){
    console.log(data)
})
9.4 Promise和callback方式对比

callback

get('http://127.0.0.1:3000/users/4',function(userData){
    get('http://127.0.0.1:3000/jobjs',function(jobsData){
        var htmlStr = template('tpl', {
            user: JSON.parse(userData),
            jobs: JSON.parse(jobsData)
        })
        console.log(htmlStr)
        document.querySelector('#user_form').innerHTML = htmlStr
    })
}) 

promise

var data = {}
$.get('http://127.0.0.1:3000/users/4')
.then(function(user){
    data.user = user
    return $.get('http://127.0.0.1:3000/jobjs')
})
.then(function(jobs){
    data.jobs = jobs    
    var htmlStr = template('tpl', data)
    document.querySelector('#user_form').innerHTML = htmlStr
})

猜你喜欢

转载自blog.csdn.net/yw00yw/article/details/82377664