node.js day5 mongodb mongoose异步函数 异步操作(Promise then)

day 5

异步函数 回调函数

同步函数:一行一行的执行代码到函数结束

(function add(a, b) {
    return a + b;
})(x, y);

异步编程:不会按一横一行的的执行
想要得到setimeout的结果只能用回调函数
异步函数 永远是在普通代码执行完之后执行
add(1,2) 不会返回结果 只会返回undefined,因为add函数没有异步函数的返回值
例1:

function add(x, y) {
    setTimeout(function() {
        var ret = x + y;
        return ret;
    }, 1000)
}
//想要得到setimeout的结果只能用回调函数   
//异步函数 永远是在普通代码执行完之后执行


log(add(1,2));//undefined

例2:


function add(x, y) {
    var ret;
    setTimeout(function() {
        ret = x + y;
    }, 1000)
    return ret;
}
console.log(add(1, 2)); //undefined   ret声明了之后跳过异步函数就返回了
回调函数就是为了的到异步编程的结果

如 setTimeout ,readFile ,writeFile,ajax都是异步编程,想要得到异步编程的结果必须用回调函数

callback参数当做参数传入异步函数

//通过回调函数拿异步函数的结果
function add(x, y, callback) {
    var ret;
    setTimeout(function() {
        ret = x + y;
        callback(ret);
    }, 1000)
}
(add(1, 2, function(ret) {
    console.log(ret);
}));

!!通过回调函数 就能够对 异步函数的结果进行运算
这里不能用闭包 因为这是异步操作 ,异步函数永远在最外层函数内的其他代码执行完再执行

Ajax封装

~~封装Ajax 想要的到onload中的结果必须用回调函数

function getAjax(url, callback) {
    var Oreq = new XMLHttpRequest;
    //当请求调用成功之后调用的函数
    Oreq.onload = function() {
        callback(Oreq.responseText);
    }
    Oreq.open("get", url, true);
    Oreq.send();
}
getAjax("json.json", function(responseText) {
    console.log(responseText);
})

JavaScript模板化问题

JavaScript天生不支持模块化(exports,require) ,只有在Node中才有

模板化:通过API进行文件之间的依赖,模板作用域 ,NODE中支持CommonJS所以可以模板化
不能模板化:通过script src link 等来引用加载,而且必须考虑加载的顺序问题

在浏浏览器中也有几个第三方API提供模块化内容(解决模块化问题):

require.js 第三方库 AMD
sea.js 第三方库CMD
commonJS,AMD,CMD都是民间的api,Ecmascript2016官方标准已经发布,但是很多JavaScript运行环境还不支持
解决方法:

在这里插入图片描述

npm5以后下载安装包不需要用--save就会加入到package-lock.json文件

  1. 下载express会有一堆文件 因为 express也用到了其他依赖
  2. lock是用来锁定版本的,当删除了某个安装包如express通过npm install下载时会下载锁定的版本

finde和findIndex的底层原理

node.js day5 mongodb mongoose异步函数 异步操作(Promise then)_第1张图片

引用了回调函数的运用也是闭包

var users = [
    { id: 1, name: "a" },
    { id: 2, name: "a" },
    { id: 3, name: "a" },
    { id: 4, name: "a" }
]

//给Array添加方法
//conditionFunc就是写的数组需要满足的条件
Array.prototype.myFind = function(conditionFunc) {
//conditionFunc =  (function(term, index) {return term.id = 4;
})
    for (var i = 0; i < this.length; i++) {
        if (conditionFunc(this[i], i)) {
            return this[i]; //将满足条件函数的数组项返回   也可以返回i就是满足条件的数组的index
        }
    }

}
var ret = myFind(function(term, index) {
    return term.id = 4;
})
console.log(ret);

关系型数据库(SQL)和菲关系型数据库

表就是关系
或者说是表与表之间存在关系
  1. 所有的关系型数据库都需要通过sql语言来操作
  2. 所有的关系型数据库在操作之前都需要设计表结构
  3. 而且数据表还支持约束
  4. 非关系型数据酷非常的灵活
  5. MonggoDb是长得最像关系型数据库的非关系型数据库
  6. 也就是说你可以任意的往里面存数据

MongoDB

下载与安装以及配置环境变量

在官网下载速度下载很慢可以复制下载链接到迅雷下载 ,安装一直next就行了
配置环境变量 将mongodb中的bin文件路径设置到环境变量的path里
通过cmd操作台 mongod -- version查看是否安装完成

开启关闭MongoDB

在这里插入图片描述

关闭:

crlt +c

修改数据库路径

C:\Users\Mr.Deng>mongod --dbpath = “新的路径”

连接和退出数据库

连接数据库: 开启数据库后在新的cmd中输入 mongo// 会自动链接本机的数据库
断开数据库 : exit

基本操作

查看所有的数据库 show dbs
最开始有系统默认的数据库
在这里插入图片描述

查看当前所在的数据库 db
如果没有在某个数据库 会自动到test数据库 但是其实没有这个库
在这里插入图片描述
切换到指定的数据(如果没有则自动创建): use 数据库名称
虽然创建了数据库但是 总的数据库里还没有这个库
node.js day5 mongodb mongoose异步函数 异步操作(Promise then)_第2张图片

插入数据
当某个库中有了数据以后 数据库就能查找出来
node.js day5 mongodb mongoose异步函数 异步操作(Promise then)_第3张图片
查询students中的数据
对象数据自动添加了 id
node.js day5 mongodb mongoose异步函数 异步操作(Promise then)_第4张图片
可以自由的添加不同类型的对象 但是关系型数据库就不行
node.js day5 mongodb mongoose异步函数 异步操作(Promise then)_第5张图片

在node中操作mongoDB

方法一:使用官方文档操作

https://github.com/mongodb/node-mongodb-native

方法二:使用mongoose

网址:http://www.mongoosejs.net
下载: npm i mongoose
开启数据库 添加数据:在JavaScript中添加如下代码
这样就可以在JavaScript中添加

const mongoose = require('mongoose');
//连接数据库   这个数据库不用存在 插入数据后会自动生成
mongoose.connect('mongodb://localhost/test');
//创建一个模型
//就是在设计数据库
//MongoDB是动态的,非常灵活,只需要在代码中设计你的数据库就可以了 cat是个数组 存储了对象

const Cat = mongoose.model('Cat', { name: String });
//实例化一个Cat

const kitty = new Cat({ name: 'Zildjian' });
kitty.save().then(() => console.log('meow'));

当在test中添加了cats后就能在mongo数据库中找到了
mongoose默认连接在test中
node.js day5 mongodb mongoose异步函数 异步操作(Promise then)_第6张图片

mongoose开始

新增一个文档步骤:

const mongoose = require('mongoose');

var Schema = mongoose.Schema;
//1.第一步连接数据库
mongoose.connect('mongodb://localhost/test');

var Schema = mongoose.Schema;

//2.设计文档结构(表结构)结构
var userSchema = new Schema({
    username: {
        type: String,
        required: true //必须有
    },
    password: {
        type: String,
        required: true
    },
    emai: {
        type: String
    }
})

//3.将一个文档结构发布为模型
//mongoose.model()就是用来发布架构发布为model
//第一个参数为大写名词单字符串用来表示数据库名称,mongoose会自动把大写字符串转化为小写复数的集合名称
// 如User  变为  users
//第二个参数  架构userSchema
var User = mongoose.model('User', userSchema);

//4.当我们有了构造函数之后就可以对users集合中的数据为所欲为了
var admin = new User({
        username: 'admin',
        password: '123456',
        email: "[email protected]"
    })
    //将数据永久化

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

在node中执行这个js文件就可以了 node demo.js
注意数据库必须始终开着
结果:
node.js day5 mongodb mongoose异步函数 异步操作(Promise then)_第7张图片

添加数据
var admin = new User({
    username: 'admin',
    password: '123456',
    email: "[email protected]"
})
var dz = new User({
        username: 'dz',
        password: '123444',
        email: '[email protected]'
    })
查询数据

查询所有数据: User.find(回调函数)

//查询所有数据
//再次证明了User集合中是一个数组
User.find(
    function(err, ret) {
        if (err) {
            console.log('查询失败')
        } else {
            console.log(ret)
        }
    }
)

按条件查询所有数据:User.find(条件,回调函数)

按条件查询某个数据:User.findOne(条件,回调函数)

// 按条件查询
// User.find({ 查找的条件 }, 回调函数)
console.log('按条件查找数据:');
User.findOne({ username: 'dz' }, function(err, ret) {
    if (err) {
        console.log('按条件查询失败')
    } else {
        console.log(ret)
    }
})
删除数据

删除所有:User.remove({条件},回调函数)
根据条件删除某一个:model.findOneAndRemove(conditions,[options],[callback])
根据ID删除某一个:model.findByIdAndRemove(conditions,[options],[callback])

User.remove({ username: 'admin' }, function(err, ret) {
    if (err) {
        console.log('删除失败')
    }
})
User.find(
    function(err, ret) {
        if (err) {
            console.log('查询失败')
        } else {
            console.log(ret)
        }
    }
)
修改数据

User.findByIdAndUpdate(‘id’,{修改的内容},回调函数);
User.findOneAndUpdate(conditions,[update],[options],callback)

//更新数据
User.findByIdAndUpdate('606d5d14b8ae6141345f5857', {
    username: 'dzz',
    password: '12323'
}, function(err, ret) {
    if (err) {
        console.log('修改失败')
    } else {
        console.log('修改成功')
    }
})

mongoDB数据库概念

node.js day5 mongodb mongoose异步函数 异步操作(Promise then)_第8张图片

Promise

回调地狱

回调函数中嵌套回调函数

同一个作用域中的回调函数的执行顺序是随机的 无法保证执行顺序
//回调函数执行顺序是随机的

var fs = require('fs');
fs.readFile('./demo1.js', function(err, ret) {
    if (err) {
        console.log('aaa');
    }
})
fs.readFile('./demo1.js', function(err, ret) {
    if (err) {
        console.log('bbb');
    }
})
fs.readFile('./demo1.js', function(err, ret) {
    if (err) {
        console.log('ccc');
    }
})

结果:每次执行的结果不一样,因为JavaScript是多线程的
node.js day5 mongodb mongoose异步函数 异步操作(Promise then)_第9张图片

解决方法:回调地狱 可以让异步函数有顺序的执行

回调地狱:异步函数嵌套异步函数

var fs = require('fs');
fs.readFile('./demo1.js', function(err, ret) {
    if (err) {
        console.log('aaa');
    }
    fs.readFile('./demo1.js', function(err, ret) {
        if (err) {
            console.log('bbb');
        }
        fs.readFile('./demo1.js', function(err, ret) {
            if (err) {
                console.log('ccc');
            }
        })
    })
})

结果:每次都是按顺序执行node.js day5 mongodb mongoose异步函数 异步操作(Promise then)_第10张图片

promise的作用:为了解决回调地狱编码方式带来的丑陋的问题,在ES6中新增了一个API名字叫做promise,是一个构造函数

promise有两种状态,默认状态是pending(正在做)
promise
node.js day5 mongodb mongoose异步函数 异步操作(Promise then)_第11张图片

使用方法

new promise()
promise本身不是异步的,只是一个容器,一旦创建就开始执行
.then()就是一个回调函数来得到promise中的异步函数的结果,根据不同状态代用不同回调函数

//promise函数
var fs = require('fs');
var p1 = new Promise(function(resolve, reject) {
        fs.readFile('./demo1.js', function(err, ret) {
            if (err) {
                reject(err);
            } else {
                // 承诺容器成功了
                // 将容器的pending状态改为Resolved状态
                //也就是说这里调用的方法其实是resolve方法实际上是then方法传递的那个function,回调函数的到结果
                resolve(ret)
            }
        })
    })
    // p1就是那个承诺结果
p1.then(
    //当状态位resolved执行这个函数,function就是resolve(ret)
    function(data) {
        console.log(data);
    },
    //这个funtion就是reject(err)
    function(err) {
        console.log('读取文件失败了', err);
    });
.then回调函数解决回调地狱问题

.then会接收前一个函数的返回值

var fs = require('fs');
var p1 = new Promise(function(resolve, reject) {
    fs.readFile('./demo1.json', 'utf8', function(err, ret) {
        if (err) {
            reject(err);
        } else {
            // 承诺容器成功了
            // 将容器的pending状态改为Resolved状态
            //也就是说这里调用的方法其实是resolve方法实际上是then方法传递的那个function,回调函数的到结果
            resolve(ret)
        }
    })
})

var p2 = new Promise(function(resolve, reject) {
    fs.readFile('./demo2.json', 'utf8', function(err, ret) {
        if (err) {
            reject(err);
        } else {
            // 承诺容器成功了
            // 将容器的pending状态改为Resolved状态
            //也就是说这里调用的方法其实是resolve方法实际上是then方法传递的那个function,回调函数的到结果
            resolve(ret)
        }
    })
})

var p3 = new Promise(function(resolve, reject) {
        fs.readFile('./demo3.json', 'utf8', function(err, ret) {
            if (err) {
                reject(err);
            } else {
                // 承诺容器成功了
                // 将容器的pending状态改为Resolved状态
                //也就是说这里调用的方法其实是resolve方法实际上是then方法传递的那个function,回调函数的到结果
                resolve(ret)
            }
        })
    })
    // p1就是那个承诺结果
p1.then(
        //当状态位resolved执行这个函数,function就是resolve(ret)
        function(data) {
            console.log(data);
            return p2;
        },
        //这个funtion就是reject(err)
        function(err) {
            console.log('读取文件失败了', err);
        })
    .then(function(data) {
        console.log(data);
        return p3;
    })
    .then(function(data) {
        console.log(data);
    })

分别声明几个promise容器,.then会接受上一个函数的resolved状态的函数的结果作为funtion函数,如果上一个resolved没有返回任何结果 funtion函数返回undefined
node.js day5 mongodb mongoose异步函数 异步操作(Promise then)_第12张图片

promise封装readFile函数

promise可以封装所有异步函数

//通过promise函数封装readFile函数
var fs = require('fs');

function PreadFile(filePath) {
    return new Promise(function(resolve, reject) {
        fs.readFile(filePath, 'utf8', function(err, ret) {
            if (err) {
                reject(err);
            } else {
                // 承诺容器成功了
                // 将容器的pending状态改为Resolved状态
                //也就是说这里调用的方法其实是resolve方法实际上是then方法传递的那个function,回调函数的到结果
                resolve(ret)
            }
        })
    })
}

PreadFile('./demo1.json')
    .then(
        function(data) {
            console.log(data);
            return PreadFile('./demo2.json')
        })
    .then(function(data) {
        console.log(data);
        return PreadFile('./demo3.json')
    })
    .then(
        function(data) {
            console.log(data);
        })

promise的应用场景

通过两个接口获取两个数据的时候,必须用嵌套函数,这时候就可以用promise
如Ajax请求两个文件的数据时

用promise封装ajax

只有promise函数才可以.then所以必须返回promise函数

function Pget(url, callback) {
    return new Promise(
        function(resolve, reject) {
            var Oreq = new XMLHttpRequest();
            //当请求调用成功之后调用的函数
            Oreq.onload = function() {
                //callback&&callback()两个函数
                callback && callback(JSON.parse(Oreq.responseText));
                resolve(JSON.parse(Oreq.responseText));
            }
            Oreq.onerror = function(error) {
                reject(error);
            }
            Oreq.open("get", url, true);
            Oreq.send();
        }
    )
}

//既可以pget(url,回调函数)   也可以pget(url).then
// Pget('./json.json').then(function(data) {
//     console.log(data);
// })
Pget('./json.json', function(data) {
    console.log(data);
})

promise数据库操作例子

数据库的所有操作都是异步操作
实现功能:先查找后判断是否存在再创建数据
.then会接受前面一个函数返回的数据作为.then函数的参数或者函数


// 用户注册案例
//先判断用户是否存在
//如果不存在就创建并保存 
//链式查找

User.findOne({
    username: '666'
}).then(function(data) {
    if (data) {
        console.log('用户已存在');
    } else {
        return new User({
            username: '666',
            password: '3333',
            // emai: '[email protected]'
        }).save();
    }
}).then(function(User) {

})

你可能感兴趣的:(web后端)