1.Promise定义、应用场景及其理解
Promise是ES6中为我们提供的一种异步编程解决方案,用以解决 callback嵌套 问题。
在Promise中共有 三种状态,分别为:pending(进行中)、fulfiled(已成功)、rejected(已失败)。
上述Promise状态一旦发生改变不可回溯。
在Promise中会传入两个参数,分别是成功时传参resolve和失败时传参reject。
Example:
const promise = new Promise(function(resolve,reject){
if(state==0){ //如果状态为1时执行resolve
resolve(value);
}else{
reject(value);
}
})
Promise核心方法:
==.then==
可以接受两个回调函数作为参数。第一个回调函数是Promise对象的状态变为 resolved时调用, 第二个 回调函数是 Promise对象的状态变为rejected时调用。其中,第二个函数是可选的,不一定要提供。 这两 个函数都接受 Promise 对象传出的值作为参数。
Example:
timeout方法返回了一个Promise实例,表示过一段时间才会发生的结果。
过了指定时间(s)参数后,Promise实例状态为resolved就会触发then方法绑定的回调函数
function timeout(s){
return new Promise((resolve,reject) => {
setTimeout(resolve,s,"LeeHao");
});
}
timeout(3000).then((value)=>{
console.log(value);
})
==.all==
该方法会将多个promise实例包装成一个实例,只有这几个实例全部为resolved时
才会调用 新实例 Promise.all 方法后面的回调函数。
Example:
const promises = [2, 3, 5, 7, 11, 13].map(function (id) {
return getJSON('/post/' + id + ".json");
});
Promise.all(promises).then(function (posts) {
// ...
}).catch(function(reason){
// ...
});
==.race==
该方法也会将多个实例包装为一个新的实例,只要有一个实例为resolved时
就会调用新实例 Promise.race后面的函数。
Example:
onst p = Promise.race([
fetch('/resource-that-may-take-a-while'),
new Promise(function (resolve, reject) {
setTimeout(() => reject(new Error('request timeout')), 5000)
})
]);
p
.then(console.log)
.catch(console.error);
==.finally==
finally()方法用于指定不管Promise对象最后状态如何,都会执行的操作。
2.async 和 await
async 函数是什么?一句话,它就是 Generator 函数的语法糖。
用Generator 函数,依次读取两个文件。
const fs = require('fs');
const readFile = function (fileName) {
return new Promise(function (resolve, reject) {
fs.readFile(fileName, function(error, data) {
if (error) return reject(error);
resolve(data);
});
});
};
const gen = function* () {
const f1 = yield readFile('/etc/fstab');
const f2 = yield readFile('/etc/shells');
console.log(f1.toString());
console.log(f2.toString());
};
上面代码的函数 gen 可以写成 async 函数,就是下面这样。
const asyncReadFile = async function () {
const f1 = await readFile('/etc/fstab');
const f2 = await readFile('/etc/shells');
console.log(f1.toString());
console.log(f2.toString());
};
一比较就会发现, async 函数就是将 Generator 函数的星号( * )替换成 async ,将 yield 替换成 await ,仅此而已。
async 函数对 Generator 函数的改进,体现在以下四点。
(1)内置执行器。
Generator 函数的执行必须靠执行器,所以才有了 co 模块,而 async 函数自带执行器。也就是说, async 函数的执行,与普通函数一模一样,只要一行。
asyncReadFile();
上面的代码调用了 asyncReadFile 函数,然后它就会自动执行,输出最后结果。这完全不像 Generator 函数,需要调用 next 方法,或者用 co 模块,才能真正执行,得到最后结果。
(2)更好的语义。
async 和 await ,比起星号和 yield ,语义更清楚了。 async 表示函数里有异步操作, await 表示紧跟在后面的表达式需要等待结果。
(3)更广的适用性。
co 模块约定, yield 命令后面只能是 Thunk 函数或 Promise 对象,而 async 函数的 await 命令后面,可以是 Promise 对象和原始类型的值(数值、字符串和布尔值,但这时会自动转成立即 resolved 的 Promise 对象)。
(4)返回值是 Promise。
async 函数的返回值是 Promise 对象,这比 Generator 函数的返回值是 Iterator 对象方便多了。你可以用 then 方法指定下一步的操作。
进一步说, async 函数完全可以看作多个异步操作,包装成的一个 Promise 对象,而 await 命令就是内部 then 命令的语法糖。
基本用法
async 函数返回一个 Promise对象,可以使用 then方法添加回调函数。当函数执行的时候,一旦遇到 await 就会先返回,等到异步操作完成,再接着执行函数体内后面的语句。
下面是一个例子。
async function getStockPriceByName(name) {
const symbol = await getStockSymbol(name);
const stockPrice = await getStockPrice(symbol);
return stockPrice;
}
getStockPriceByName('goog').then(function (result) {
console.log(result);
});
上面代码是一个获取股票报价的函数,函数前面的 async 关键字,表明该函数内部有异步操作。调用该函数时,会立即返回一个 Promise 对象。
下面是另一个例子,指定多少毫秒后输出一个值。
function timeout(ms) {
return new Promise((resolve) => {
setTimeout(resolve, ms);
});
}
async function asyncPrint(value, ms) {
await timeout(ms);
console.log(value);
}
asyncPrint('hello world', 50);
上面代码指定 50 毫秒以后,输出 hello world 。