vue1-day8

Promise

关于promise解决回调地狱问题的说明

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
//需求:你要封装一个方法,我给你一个要读取文件的路径,你这个方法能帮我读取文件,并把内容返回给我

const fs = require('fs')
const path = require('path')

//这是普通读取文件的方式
<!-- fs.readFile(path.join(__dirname,'./files/1.txt'),'utf-8',(err,data) => {
if(err) throw err
console.log(data)
}) -->

//封装方法的初衷:给定文件路径,返回读取到的文件内容
//我们可以规定以下,callback中有两个参数,第一个参数就是失败的结果,第二个参数就是成功的结果;同时我们规定了,如果成功后,返回的结果应该房屋callback参数的第二个位置,此时第一个位置由于没有出错所以放一个努力了;如果失败了第一个位置参数防止erro对象,第二个位置放一个undefined
function getFilePath(fpath,callback){
//该文件读取方法是一个异步方法,主程序不会去管他,而会直接跳过,所以无法获得读取文件的return值
fs.readFile(path.join(fpath,'utf-8',(err,data) => {
//错误发生后,就立即进入if分支,if后面的额代码就不会执行,解决办法就是在throw err前面加一个return
if(err) return callback(err)
<!-- console.log(data) -->
callback(null,data)//使用回调来获取读取文件的值
})
}

//调用
getFilePath(path.join(__dirname,'./files/1.txt'),(data) => {
console.log(data)
if(err) return console.log(err.message)
console.log(data)
})

回调地狱就是回调里面嵌套回调,一直会嵌套下去,当嵌套多了层级多了的时候,就会影响直观感受和代码的维护,物品们就称这种回调现象为回调地狱。解决办法是:使用ES6的Promise(本质就是用来解决回调地狱,并不能帮我们减少代码量),把多层的嵌套改成串联的使用。

Promise基本概念介绍【重要】

1.Promise是一个构造函数,既然是构造函数我们就可以new Promise(),得到Promise实例
2.在Promise上,有两个函数,分别叫做resolve(成功之后的回调函数)和reject(失败之后的回调函数)
3.在Promise构造函数的Prototype属性上有一个.then()方法,也就是说只要是Promise构造函数创建的实例,都可以访问到.then()方法
4.Promise表示一个异步操作,每当我们new一个Promise的实例,这个实例就表示一个具体的异步操作;
5.既然Promise创建的实例是一个异步操作,那么这个异步操作的结果只能有两种状态:异步执行成功了(需要在内部调用成功回调函数 resolve把结果返回给调用者)、异步执行失败了(需要在内部调用失败的回调函数reject把结果返回给调用者);由于Promise的实例是一个异步操作,所以内部拿到操作的结果后,无法使用return把操作的结果返回给调用者;这时候只能使用回调函数的形式来吧成功或失败的结果返回给调用者。
6.我们可以在new出来的Promise实例上调用.then()方法,【预先】为这个Promise异步操作指定成功(resolve)和失败(reject)回调函数。

使用:

1
2
3
4
5
6
7
8
9
//这里new出来的promise只是代表【形式上】的一个异步操作
//什么是形式上的异步操作:就是说我们只知道它是一个异步操作,但是做什么具体的异步事情,目前还不清楚
//var promise = new Promise()

//这是一个具体的异步操作,其中,使用function指定一个具体的异步操作
/* var promise = new Promise(function(){
//这个function内部写的就是具体的异步操作
fs.readFile()
}) */

每当new一个Promise实例的时候,就会立即执行这个异步操作中的代码,也就是说,new的时候,除了能够得到一个Promise额实例之外,还会立即调用我们为Promise构造函数传递的哪个function,执行这个function中的额异步操作代码.如果不想要立即执行,需要用函数包裹一下这个函数如下所示。

then方法,谁调用谁写

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
//初衷:给路径,返回读取到的内容
//以下的代码,因为promise是立即执行的,所以执行promise的时候,先then先执行,先把resolve和reject具体化,然后再执行function内部的其他操作
function getFileParh(fpath){
var promise = new Promise(function(resolve,reject){
fs.readFile(fpath,'utf-8',(err,data) => {
/*if (err) throw err
console.log(data)*/
if(err) reject(err)
resolve(data)
})
})


return promise
}

getFilePath('./files')
.then(function(data){
console.log(data)
},function(err){
console.log(err》message)
})

注意:通过.then指定回调函数的时候,成功的回调函数必须穿,但是失败的回调函数可以省略不传

打开promise的正确方式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
//初衷:给路径,返回读取到的内容
//以下的代码,因为promise是立即执行的,所以执行promise的时候,先then先执行,先把resolve和reject具体化,然后再执行function内部的其他操作
function getFileParh(fpath){
var promise = new Promise(function(resolve,reject){
fs.readFile(fpath,'utf-8',(err,data) => {
/*if (err) throw err
console.log(data)*/
if(err) reject(err)
resolve(data)
})
})


return promise
}

//读取文件1
//在上一个.then中,返回一个新的promise实例,可以继续使用下一个.then来处理。即当前.then所处理的是上一个函数对return的结果
getFilePath('./files')
.then(function(data){
console.log(data)

//读取文件2
return getFilePath('./files2')
})
.then(function(data){
console.log(data)
//读取文件3
return getFilePath('./files3')
})
.then(function(data){
console.log(data)
})

捕获异常的两种方式

如果前面的promise执行失败,我们不想让后续的promise操作终止,可以为每个promise指定失败的回调

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
getFilePath('./files')
.then(function(data){
console.log(data)

//读取文件2
return getFilePath('./files2')
},function(err){
console.log(err.message)
})
.then(function(data){
console.log(data)
//读取文件3
return getFilePath('./files3')
})
.then(function(data){
console.log(data)
})
.catch(function(data){
console.log(data.message)
})

当我们有这样的需求:哪怕前面的promise执行失败了,但是不要影响后续的正常执行,此时我们可以单独为每个promise,通过.then指定下一直白的回调;
有时候,我们有这样的需求,跟上面的需求刚好相反:如果后续的promise执行,依赖于前面promise执行的结果,如果前面的失败了,则后面的就没有继续执行下去的意义了,此时,我们想要实现,一旦有报错,则立即终止所有promise的执行.catch的作用就是,不管前面的哪一个出错了,哪怕是promise或者.then出错了,都立即停止执行.catch,进行错误的捕获(前面任何一个出错了后面的都不再执行相关操作直接跳到catch)

catch的作用:如果前面有任何的promise执行失败,则立即停止所有promise的执行,并马上进入catch去处理promise中抛出的异常,但是执行成功的promise还是会执行成功

jQuery中的ajax也可以使用promise

-------------本文结束感谢您的阅读-------------