异步编程包含以下几种形式:
- callback function
- promise
- generator function (co)
- async await function
callback function
嵌套太深,看起来太费劲。(不推荐使用。)
function async1(fn) {
setTimeout(function(){
fn('hello');
},1)
}
function async2(fn) {
setTimeout(function(){
fn('world');
},1);
}
async1(function(data){
async2(function(data1){
console.log(data + ',' + data1);
})
})
promise
- 可以将异步操作以同步操作的流程表达出来,避免了层层嵌套的回调函数。此外,Promise对象提供统一的接口,使得控制异步操作更加容易。
- Promise也有一些缺点。首先,无法取消Promise,一旦新建它就会立即执行,无法中途取消。其次,如果不设置回调函数,Promise内部抛出的错误,不会反应到外部。当处于Pending状态时,无法得知目前进展到哪一个阶段(刚刚开始还是即将完成)。
- pending ——>resolved——>rejected
- new Promise(function(resolve, reject){}); // reject 可选参数
- promise.all
- promise.race
function promise1() {
return new Promise((resole, reject) => {
setTimeout(() => {
resole("Hello"); //[@4](/user/4) 返回正确结果
}, 1)
})
}
function promise2(data1) {
return new Promise((resole, reject) => {
setTimeout(() => {
resole(data1 + " world");
}, 1)
}, 1)
}
promise1()
.then(function (v) {
return promise2(v)
})
.then(function (data2) {
console.log(data2)
})
.catch(function (e) {
console.log(e)
});
promise.all
合并请求
function timeout(duration) {
return new Promise((resolve, reject) => {
setTimeout(function(){
resolve('hello world');
}, duration);
});
}
var p = timeout(200).then(() => {
return Promise.all([timeout(100), timeout(200)]);
})
p.then(v => {
console.log(v)
})
promise.race
当有一个请求返回时,返回最新值。
var p1 = new Promise(function(resolve, reject) {
setTimeout(resolve, 0, 'success');
});
var p2 = new Promise(function(resolve, reject) { });
var p2 = new Promise(function(resolve, reject) { });
var race = Promise.race( [p1, p2, p3] );
race.then(function(result) {
console.log(result);
});
// Output:
// success
var race = Promise.race( [Promise.reject('failure'),
Promise.resolve('success')] );
race.catch(function(result) {
console.log(result);
});
// Output:
// failure
generator function
es6 的函数生成器 // 最大特点就是可以交出函数的执行权(即暂停执行),配合yield 关键字使用。
function* fibonacci() {
yield 1;
yield 2;
}
var it = fibonacci();
console.log(it); // "Generator { }"
console.log(it.next()); // 1
console.log(it.next()); // 2
console.log(it.next()); //undefined
function* foo() {
yield 0;
yield 1;
}
function* bar() {
yield 'x';
yield* foo();
yield 'y';
}
for (let v of bar()){
console.log(v);
};
// 输出结果:x, 0, 1, y
co (TJ)
实现原理封装了promise
var co = require('co');
co(function *(){
// yield any promise
var result = yield Promise.resolve(true);
}).catch(onerror);
co(function *(){
// resolve multiple promises in parallel
var a = Promise.resolve(1);
var b = Promise.resolve(2);
var c = Promise.resolve(3);
var res = yield [a, b, c];
console.log(res);
// => [1, 2, 3]
}).catch(onerror);
// errors can be try/catched
co(function *(){
try {
yield Promise.reject(new Error('boom'));
} catch (err) {
console.error(err.message); // "boom"
}
}).catch(onerror);
function onerror(err) {
// log any uncaught errors
// co will not throw any errors you do not handle!!!
// HANDLE ALL YOUR ERRORS!!!
console.error(err.stack);
}
终极解决方案 async / await
- async/await是写异步代码的新方式,以前的方法有回调函数和Promise。
- async/await是基于Promise实现的,它不能用于普通的回调函数。
- async/await与Promise一样,是非阻塞的。
- async/await使得异步代码看起来像同步代码。
- 节约代码。
- async/await try/catch可以同时处理同步和异步错误
const f = async() => {
return 'hello world';
};
const testAsync = async () => {
try {
const t = await f();
console.log(t);
const s = await s();
} catch(e) {
console.log(e);
}
};
testAsync();
同上,一样的效果
const f = () => {
return new Promise((resole, reject) => {
return 'hello world';
})
}
const testAsync = async () => {
try {
const t = await f();
console.log(t);
const s = await s();
} catch(e) {
console.log(e);
}
};
testAsync();
说明async 原理也是对promise进行了封装。