Promise是前端JavaScript中用于处理异步操作的一种对象。比传统的解决方案:回调函数和事件,更合理和更强大。Promise在JavaScript中表示一个异步操作的最终完成(或失败)及其结果值的表示。通俗讲,Promise是对未来事情的承诺,承诺不一定能完成,但是无论是否能完成都会有一个结果。它有三种状态:
- 等待态(Pending):初始状态,既不是成功也不是失败。
- 执行态(Fulfilled):表示操作成功完成。
- 拒绝态(Rejected):表示操作失败。
一旦Promise的状态从pending变为fulfilled或rejected,它就不会再次改变状态。
const fetchData = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (Math.random() < 0.5) {
resolve('Data fetched successfully!');
} else {
reject('Failed to fetch data.');
}
}, 1000);
});
};
fetchData()
.then(data => console.log(data)) // 50% chance of seeing this message
.catch(error => console.error(error)); // 50% chance of seeing this message
这段代码中,fetchData函数返回一个Promise对象,模拟了一个异步操作(这里是一个延迟操作)。这个操作有一半的可能性成功,有一半的可能性失败。然后我们使用.then()和.catch()方法来处理成功和失败的两种可能结果。
Promise 用来预定一个不一定能完成的任务,要么成功,要么失败。在具体的程序中具体的体现,通常用来封装一个异步任务,提供承诺结果。Promise 是异步编程的一种解决方案,主要用来解决回调地狱的问题,可以有效的减少回调嵌套。真正解决需要配合async/await。
Promise对象在JavaScript中用于处理异步操作,它具有以下特点:
- 对象状态不受外界影响:Promise对象代表一个异步操作,有三种状态:pending(进行中)、fulfilled(已成功)和rejected(已失败)。只有异步操作的结果可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。这也是Promise这个名字的由来,它的英语意思就是“承诺”,表示其他手段无法改变。
- 状态改变后无法再变:一旦Promise的状态从pending变为fulfilled或rejected,它就不会再次改变状态。Promise有两种状态的改变:pending→fulfilled和pending→rejected。
- 立即执行:一旦新建Promise就会立即执行,无法中途取消。
Promise的立即执行是指一旦创建Promise对象,就会立即执行相关的异步操作,而不会等待任何代码或事件触发。这是因为Promise对象的创建本质上会立即触发一个异步操作,无论这个操作是否会在将来的某个时间点完成。
举个例子,假设有一个函数foo(),它返回一个Promise对象,这个Promise对象在异步操作成功时resolve,失败时reject。当调用foo()函数时,Promise对象就会被创建,并且相关的异步操作也会立即开始执行。
function foo() {
return new Promise((resolve, reject) => {
// 异步操作,比如网络请求
// ...
});
}
// 调用foo()函数,Promise对象被创建,异步操作立即开始执行
foo().then(result => {
// 异步操作成功,处理结果
}).catch(error => {
// 异步操作失败,处理错误
});
在这个例子中,foo()函数返回的Promise对象在创建时会立即开始执行其中的异步操作,不管是否有代码或事件触发。这就是为什么说Promise具有立即执行的特点。
- 错误处理:如果不设置回调函数callback,Promise抛出的内部错误就不会反应到外部。处于pending状态时,无法得知进行到哪一阶段。
Promise的错误处理是Promise的一个重要特性,它允许您指定一个回调函数来处理Promise操作失败时的错误。
通常,当Promise操作失败时,它会变为rejected状态,并且可以通过.catch()方法来捕获错误。这个方法接受一个回调函数作为参数,并在Promise操作失败时被调用,传递错误信息作为参数。
const promise = new Promise((resolve, reject) => {
// 异步操作,可能会失败
// ...
});
promise
.then(result => {
// 异步操作成功,处理结果
})
.catch(error => {
// 异步操作失败,处理错误
console.error(error);
});
在这个例子中,当Promise操作失败时,错误会被捕获并传递给.catch()方法的回调函数,然后可以在这个函数中处理错误。如果没有使用.catch()方法来捕获错误,那么Promise错误就会被丢弃,而且你可能永远也看不到错误发生的提示。
另外,Promise的错误处理还有一个重要的特性:它只会处理最近的一个错误。一旦一个Promise操作失败并被捕获,任何其他后续的操作都会被忽略。这是因为一旦Promise变为rejected状态,它就不能再次改变状态。
Promise对象是JavaScript中处理异步操作的一种很好的方式,但它也有一些缺点,包括:
- 无法中途取消:一旦新建Promise就会立即执行,无法中途取消。这可能会在某些情况下导致资源浪费或不必要的计算。
- 错误处理:如果不设置回调函数,Promise内部抛出的错误不会反应到外部。这可能会导致难以排查的错误和异常。因此,在编写Promise代码时,我们需要特别注意错误处理机制,以便及时发现和解决错误。
- 状态管理复杂:当处于padding状态时,无法获取到底是处于哪个阶段,是刚开始还是已经结束。这可能会使得Promise的状态管理变得复杂和混乱。
尽管有这些缺点,但Promise仍然是一种非常有用的异步编程工具,它可以简化异步操作的处理,并提供更好的错误处理机制。在使用Promise时,我们需要尽可能地避免上述问题,并确保代码的可读性和可维护性。
ES6引入的进行异步编程的解决方案,具体表达:从语法上来说, Promise 是一个构造函数;从功能上来说:promise 对象用来封装一个异步操作并可以获取其成功/ 失败的结果值。异步编程包括但不限于:文件操作、数据库操作、AJAX、定时器等。之前进行异步编程直接通过回调函数的方式进行,会导致回调地狱。
- 回调函数:作为参数的函数
- 回调地狱:回调函数里面嵌套回调函数
1 Promise的初体验
点击按钮, 1s 后显示是否中奖(30%概率中奖)
若中奖弹出 恭喜您中奖
若未中奖弹出 谢谢参与
- 回调函数的实现方式
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div class="container">
<h2 class="page-header">Promise初体验</h2>
<button class="btn btn-primary" id="btn">点击抽奖</button>
</div>
<script type="text/javascript">
function rand(m, n) {
return Math.ceil(Math.random() * (n - m + 1) + m - 1);
}
const btn = document.querySelector('#btn');
btn.addEventListener('click', function () {
setTimeout(() => {
let number = rand(1, 100);
console.log(number)
if (number <= 50) {
alert('恭喜恭喜,奖品为10万 RMB 劳斯莱斯优惠券')
} else {
alert('再接再厉')
}
}, 100)
})
</script>
</body>
</html>
- promise的实现方式
这是一个基础的 JavaScript Promise 的使用案例。首先,我们需要创建一个函数,它返回一个 Promise,这个 Promise 在一秒钟后解析并返回一个随机的布尔值,代表是否中奖。然后,我们需要在 Promise 解析后处理这个布尔值,如果为 true(即中奖),则显示"恭喜您中奖",否则显示"谢谢参与"。
// 创建一个函数,返回一个 Promise
function drawLottery() {
return new Promise((resolve, reject) => {
setTimeout(() => {
// 一秒钟后解析 Promise,返回一个随机的布尔值
resolve(Math.random() > 0.7);
}, 1000);
});
}
// 创建一个按钮,并添加点击事件处理器
let button = document.createElement('button');
button.innerText = '抽奖';
button.addEventListener('click', async () => {
let isWinner = await drawLottery(); // 等待 Promise 解析,获取结果
if (isWinner) {
alert('恭喜您中奖');
} else {
alert('谢谢参与');
}
});
// 将按钮添加到页面上
document.body.appendChild(button);
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div class="container">
<h2 class="page-header">Promise初体验</h2>
<button class="btn btn-primary" id="btn">点击抽奖</button>
</div>
<script type="text/javascript">
function rand(m, n) {
return Math.ceil(Math.random() * (n - m + 1) + m - 1);
}
const btn = document.querySelector('#btn');
// 绑定单机事件
btn.addEventListener('click', function () {
// resolve 解决 - 函数类型的数据 - success
// reject 拒绝 - 函数类型的数据 - fail
const p = new Promise((resolve, reject) => {
// Promise 对象 - 可以包裹一个异步任务
setTimeout(() => {
let n = rand(1, 100)
if (n <= 30) {
resolve(n) // 将 promise 对象的状态设置为 『成功』
} else {
reject(n) // 将 promise 对象的状态设置为 『失败』
}
}, 1000);
})
// 调用then方法
// 成功就调用第一个回调函数,失败调用第二个回调
p.then((value) => {
alert('恭喜您中奖,您的中奖号码为' + value);
}, (reason) => {
alert('谢谢参与,您的号码为' + reason);
})
})
</script>
</body>
</html>
Promise构造函数的参数通常是一个函数,这个函数接收两个参数:resolve和reject。它们是两个函数,当异步操作完成时,我们调用其中一个。
let promise = new Promise((resolve, reject) => {
// 异步操作
setTimeout(() => {
if (/* 异步操作成功 */) {
resolve('成功的结果');
} else {
reject('失败的原因');
}
}, 1000);
});
- resolve函数:当异步操作成功完成时,我们调用这个函数,并将结果作为参数传递给它。这个参数可以是任何值,包括另一个Promise。
- reject函数:当异步操作失败时,我们调用这个函数,并将错误信息或错误对象作为参数传递给它。
Promise.then()函数具有两个参数。这两个参数都是可选的,它们都是函数。
- 第一个参数是一个onFulfilled函数,这个函数将在Promise解析(fulfilled)之后调用,其参数value是Promise的构造函数中回调函数中成功的结果。
- 第二个参数是一个onRejected函数,这个函数将在Promise被拒绝(rejected)之后调用,其参数reason是Promise的构造函数中回调函数中失败的原因。
let promise = new Promise((resolve, reject) => {
// 异步操作
setTimeout(() => {
if (/* 异步操作成功 */) {
resolve('成功的结果');
} else {
reject('失败的原因');
}
}, 1000);
});
promise.then(
value => {
console.log('Promise was fulfilled with value:', value);
},
reason => {
console.log('Promise was rejected with reason:', reason);
}
);
在这个例子中,如果异步操作成功,我们会在控制台中看到"Promise was fulfilled with value: 成功的结果",如果失败,我们会看到"Promise was rejected with reason: 失败的原因"。
2 fs读取文件-Promise
在Node.js中,您可以使用fs模块中的readFile函数来读取文件,并使用Promise将其包装起来。
const fs = require('fs');
function readFilePromise(filePath) {
return new Promise((resolve, reject) => {
fs.readFile(filePath, 'utf8', (err, data) => {
if (err) {
reject(err);
} else {
resolve(data);
}
});
});
}
// 使用示例
readFilePromise('/path/to/file.txt')
.then(data => console.log(data))
.catch(err => console.error(err));
在这个示例中,我们定义了一个readFilePromise函数,它接收一个文件路径作为参数,并返回一个Promise对象。在函数内部,我们使用fs.readFile函数来读取文件,并将其封装在一个新的Promise中。如果读取成功,我们将Promise解决(resolve)并返回文件内容,否则将Promise拒绝(reject)并返回错误对象。
您可以像使用任何其他Promise一样使用readFilePromise函数,使用.then()方法来处理成功的结果,使用.catch()方法来处理错误。
3 AJAX请求-Promise
AJAX请求可以使用Promise进行处理,以便更好地管理异步操作。使用Promise可以使异步代码看起来更像同步代码,从而简化代码编写和理解。
// 创建一个XMLHttpRequest对象
var xhr = new XMLHttpRequest();
// 创建一个新的Promise对象
var promise = new Promise(function(resolve, reject) {
// 设置请求方法和URL
xhr.open('GET', 'https://api.example.com/data', true);
// 设置请求成功的回调函数
xhr.onload = function() {
if (xhr.status === 200) {
resolve(xhr.response);
} else {
reject(new Error('Request failed with status: ' + xhr.status));
}
};
// 设置请求错误的回调函数
xhr.onerror = function() {
reject(new Error('Request failed'));
};
// 发送请求
xhr.send();
});
// 使用then和catch处理Promise对象的结果和错误
promise.then(function(response) {
console.log('Request succeeded', response);
}).catch(function(error) {
console.error('Request failed', error);
});
在这个示例中,我们创建了一个XMLHttpRequest对象,并使用Promise将其封装起来。在Promise对象的构造函数中,我们设置了请求方法和URL,并定义了请求成功和失败的回调函数。在成功回调函数中,我们使用resolve函数将响应传递给Promise对象,而在失败回调函数中,我们使用reject函数将错误传递给Promise对象。最后,我们使用then和catch方法处理Promise对象的结果和错误。
4 Promise对象状态属性介绍
Promise对象代表一个异步操作的最终完成(或失败)及其结果值。它具有以下几种状态属性:
- PromiseState: 这个属性表示Promise对象中函数的执行结果,主要有三种状态,包括pending(等待中)、fulfilled(已完成/已解决)和rejected(已拒绝)。
- PromiseValue: 当Promise对象的状态为fulfilled(已完成/已解决)时,PromiseValue属性就是该异步操作的结果值。
- PromiseReason: 当Promise对象的状态为rejected(已拒绝)时,PromiseReason属性就是该异步操作报出的错误原因。
一个Promise对象在任何时候只能处于一种状态。一旦状态改变,就不会再变。无论何时,我们都可以获取到Promise对象的结果值或者错误原因。
这些属性的具体表现取决于Promise对象的执行情况。一般来说,当Promise对象执行resolve或者reject函数后,它的状态就会从pending变为fulfilled或rejected,相应的结果值或错误原因也会被设置到对应的属性中。
5 Promise工作流程
let promise = new Promise((resolve, reject) => {
// 异步操作
setTimeout(() => {
if (/* 异步操作成功 */) {
resolve('成功的结果');
} else {
reject('失败的原因');
}
}, 1000);
});
promise.then(
value => {
console.log('Promise was fulfilled with value:', value);
},
reason => {
console.log('Promise was rejected with reason:', reason);
}
);
Promise对象的工作流程可以概括为以下几个步骤:
- 创建 Promise 对象:通过使用 Promise 构造函数创建一个 Promise 对象。这个对象包含一个状态和一个值,初始状态为pending。
- 执行 Promise 函数:在 Promise 构造函数中传入一个函数,这个函数会被立即执行,该函数接收两个参数 resolve 和reject,分别表示成功和失败的回调函数。
- 执行异步操作:在 Promise 函数中执行异步操作。例如,发送网络请求、读取文件等。
- 改变 Promise 状态:当异步操作完成后,调用 resolve 或 reject 函数,改变 Promise对象的状态和值。如果异步操作成功,则调用 resolve 函数并传入成功的结果,将 Promise 对象的状态改fulfilled;如果异步操作失败,则调用 reject 函数并传入失败的原因,将 Promise 对象的状态改为rejected。此时,Promise 的状态被固定,不可再改变。
- 处理 Promise 结果:使用 then 方法或 catch 方法处理 Promise 对象的结果。如果 Promise 对象的状态为fulfilled,则调用 then 方法并传入成功的回调函数,该函数接收一个参数,表示异步操作的结果;如果 Promise对象的状态为 rejected,则调用 catch 方法并传入失败的回调函数,该函数接收一个参数,表示异步操作的原因。
- 返回 Promise 对象:Promise 对象的 then 方法和 catch 方法都返回一个新的 Promise
对象,可以继续链式调用 then 方法和 catch 方法,处理异步操作的结果。
以上就是 Promise 的工作流程。需要注意的是,当异步操作完成后,Promise 的状态就不能再改变了。
6 Promise关键问题
6.1 如何修改对象的状态
Promise对象的状态是由Promise的工作流程决定的,一旦状态确定,就不能改变。这意味着你不能直接修改Promise的状态。
Promise有三种状态:pending(待定)、fulfilled(已实现)和rejected(已拒绝)。当Promise创建时,它的状态是pending。当异步操作完成时,如果操作成功,Promise的状态会变为fulfilled;如果操作失败,Promise的状态会变为rejected。一旦状态改变,就不能再改变了。
如果你想改变一个Promise的状态,你可能需要重新考虑你的代码设计。如果你需要在某个操作完成后改变一个对象的状态,你可能需要将这个状态封装在一个独立的对象中,并在Promise完成时更新这个对象的状态。
let obj = { status: 'pending' };
let promise = new Promise((resolve, reject) => {
setTimeout(() => {
obj.status = 'fulfilled';
resolve('Operation completed successfully');
}, 1000);
});
promise.then(() => {
console.log(obj.status); // 'fulfilled'
});
在这个例子中,我们将状态存储在obj对象中,并在Promise完成时更新这个对象的状态。然后,我们可以在Promise的then回调函数中访问这个新的状态。
6.2 一个Promise指定多个成功/失败的回调函数,都会调用吗?
当 promise 改变为对应状态时都会调用,改变状态后,多个回调函数都会调用,并不会自动停止。
<script>
let p = new Promise((resolve, reject) => {
// 改变Promise状态
resolve('OK');
});
///指定回调函数 - 1
p.then(value => {
console.log(value + '-1');
});
//指定回调函数 - 2
p.then(value => {
console.log(value + '-2');
});
</script>
3 改变Promise状态和指定回调函数谁先谁后
问题简化:Promise代码运行时,resolve先执行还是then先执行?
注意,指定回调和执行回调函数是不一样的,指定回调类似于p.then()中声明有哪些回调函数,执行回调则是在状态确定之后执行之前指定的回调.
两种情况都有可能
- 先改状态再指定回调(同步):改变状态 -->指定回调 并马上执行回调:
- 先指定回调再改变状态(异步):先指定回调–> 再改变状态 -->改变状态后才进入异步队列执行回调函数
什么时候才能得到数据? - 回调函数什么时候执行
- 如果先改变状态,那么当指定回调时,回调函数就会被调用,得到数据
- 如果先指定回调,那么当状态发生改变时,回调函数才被调用得到数据
如下为同步:
<script>
let p = new Promise((resolve, reject) => {
resolve('OK');
});
p.then(value => {
console.log(value);
}, reason => {
})
</script>
如下为异步,需等一秒之后执行:
promise执行器中是一个异步任务,那么就执行then,指定回调;处理执行器中的异步任务,1000ms后改变状态;再执行成功的回调函数,得到数据。
<script>
let p = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('OK');
}, 1000);
});
p.then(value => {
console.log(value);
}, reason => {
})
</script>
如下例子:
<script>
let p = new Promise((resolve, reject) => {
console.log('同步执行 ... ')
setTimeout(() => {
resolve('OK');
}, 1000);
});
p.then(value => {
console.log(value);
}, reason => {
})
</script>
4 then()方法返回的Promise的对象的状态由什么决定
(1) 简单表达: 由 then()指定的回调函数执行的结果决定
(2) 详细表达:
① 如果抛出异常, 新 promise 变为 rejected, reason 为抛出的异常
② 如果返回的是非 promise 的任意值, 新 promise 变为 resolved, value 为返回的值
③ 如果返回的是另一个新 promise, 此 promise 的结果就会成为新 promise 的结果
<script>
let p = new Promise((resolve, reject) => {
resolve('ok');
});
// 执行 then 方法
let result = p.then(value => {
}, reason => {
});
console.log(result);
</script>
① 如果抛出异常, 新 promise 变为 rejected, reason 为抛出的异常
<script>
let p = new Promise((resolve, reject) => {
resolve('ok');
});
// 执行 then 方法
let result = p.then(value => {
//1. 抛出错误
throw '出了问题';
}, reason => {
});
console.log(result);
result.then(value => {}, reason => {
console.log(reason)
})
</script>
② 如果返回的是非 promise 的任意值, 新 promise 变为 resolved, value 为返回的值
<script>
let p = new Promise((resolve, reject) => {
resolve('ok');
});
let result = p.then(value => {
return 521;
}, reason => {
});
console.log(result);
result.then(value => {
console.log(value)
}, reason => {
})
</script>
③ 如果返回的是另一个新 promise, 此 promise 的结果就会成为新 promise 的结果
<script>
let p = new Promise((resolve, reject) => {
resolve('ok');
});
let result = p.then(value => {
return new Promise((resolve, reject) => {
reject('error');
});
}, reason => {
});
console.log(result);
result.then(value => {}, reason => {
console.log(reason)
})
</script>
5 Promise如何串联多个操作任务
(1) promise 的 then()返回一个新的 promise, 可以开成 then()的链式调用
(2) 通过 then 的链式调用串连多个同步/异步任务,这样就能用then()将多个同步或异步操作串联成一个同步队列
<script>
let p = new Promise((resolve, reject) => {
setTimeout(() => {
console.log("first mission")
resolve("1000ms later resolve");
}, 1000)
})
p.then(value => {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log("second mission")
resolve();
}, 1000)
})
},
).then(value => {
return new Promise(resolve => {
setTimeout(() => {
console.log("third mission")
resolve();
}, 1000)
})
}
)
</script>
6 异常穿透
当使用 promise 的 then 链式调用时, 可以在最后指定失败的回调
前面任何操作出了异常, 都会传到最后失败的回调中处理
<script>
let p = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('OK');
}, 1000);
});
p.then(value => {
console.log(111);
}).then(value => {
console.log(222);
}).then(value => {
console.log(333);
}).catch(reason => { // 在最后指定一个失败的回调
console.warn(reason);
});
</script>
<script>
let p = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('OK');
// reject('Err');
}, 1000);
});
p.then(value => {
// console.log(111);
throw '失败啦!';
}).then(value => {
console.log(222);
}).then(value => {
console.log(333);
}).catch(reason => { // 在最后指定一个失败的回调
console.warn(reason);
});
</script>
7 如何中断promise链
- 链式调用过程中,我们希望在某一个then()方法的onResolve回调函数调用过程中,中断Promise的链式调用,只需要返回一个状态为pending的Promise对象
当没有明确返回一个promise对象,then()也会返回一个Promise对象,状态为【resolved】,结果为【underfined】
- 因为then方法的回调函数调用依据是Promise的状态是resolved或者rejected,没有pending对应的回调函数,所以后面的都没法执行了
<script>
let p = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('OK');
}, 1000);
});
p.then(value => {
console.log(111);
//有且只有一个方式
return new Promise(() => {
});
}).then(value => {
console.log(222);
}).then(value => {
console.log(333);
}).catch(reason => {
console.warn(reason);
});
</script>
11 async
函数的返回值为 promise 对象,promise 对象的结果由 async 函数执行的返回值决定
和then一样:分成三种情况执行返回值: 是非Promise对象,是一个Promise对象,是抛出异常
<script>
async function main() {
return 521
}
let res = main();
console.log(res)
</script>
<script>
async function main() {
return new Promise((resolve, reject) => {
resolve('OK')
});
}
let res = main();
console.log(res)
</script>
<script>
async function main() {
return new Promise((resolve, reject) => {
reject('ERROR')
});
}
let res = main();
console.log(res)
</script>
12 await
await 右侧的表达式一般为 promise 对象, 但也可以是其它的值:
- 如果表达式是 promise 对象, await 返回的是 promise 成功的值
- 如果表达式是其它值, 直接将此值作为 await 的返回值
注意: - await 必须写在 async 函数中, 但 async 函数中可以没有 await
- 如果 await 的 promise 失败了, 就会抛出异常, 需要通过 try…catch 捕获处理
<script>
async function main() {
let p = new Promise((resolve, reject) => {
resolve('OK');
})
let res = await p;
console.log(res)
}
main();
</script>
<script>
function test() {
return 100;
}
async function main() {
let res = test();
console.log(res)
}
main();
</script>
<script type="text/javascript">
async function main() {
let p = new Promise((resolve, reject) => {
reject('Error');
})
try {
let res3 = await p;
} catch (e) {
console.log(e);
}
}
main()
</script>
13 async与await结合实践
//回调函数的方式
fs.readFile('D:\\code\\wt-promise\\src\\hello.text', (err, data1) => {
if (err) throw err;
fs.readFile('D:\\code\\wt-promise\\src\\hello.text', (err, data2) => {
if (err) throw err;
fs.readFile('D:\\code\\wt-promise\\src\\hello.text', (err, data3) => {
if (err) throw err;
console.log(data1 + data2 + data3);
});
});
});
//async 与 await
async function main() {
try {
// 如果表达式时Promise对象,await返回的Promise成功的值
let data1 = await mineReadFile('D:\\code\\wt-promise\\src\\hello.text');
let data2 = await mineReadFile('D:\\code\\wt-promise\\src\\hello.text');
let data3 = await mineReadFile('D:\\code\\wt-promise\\src\\hello.text');
console.log(data1 + data2 + data3);
} catch (e) {
console.log(e.code);
}
}
main();