异步编程包含以下几种形式:
- 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:// successvar 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()); // 1console.log(it.next()); // 2console.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/catchedco(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进行了封装。