异步加载node
一、promise基础实例json
<script> $(function(){ function myAsync(url,data,type){ return new Promise((resolve,reject) => { let requestObj; if(window.XMLHttpRequest){ requestObj = new XMLHttpRequest(); } else{ requestObj = new ActiveXObject(); } let sendData = ""; if(type == "POST"){ //将json对象转换为字符串 sendData = JSON.stringify(data); } //参数true表示异步处理 requestObj.open(type,url,true); requestObj.send(sendData); requestObj.onreadystatechange = () => { //readyState == 4,相应内容解析完成 if(requestObj.readyState == 4){ // 服务器成功处理请求 if(requestObj.status == 200){ let obj = requestObj.response; if( typeof obj !== 'object'){ obj = JSON.parse(obj) } resolve(obj) } else{ reject(obj) } } } }) } $("#btn").on("click",()=>{ myAsync("http://jsonplaceholder.typicode.com/posts","GET") .then( (rsp) => { console.log("成功!",rsp)}) .catch((error)=>{ console.log(error) }) }); }); </script>
二、Promise.all方法能够接收多个 promise 做为参数,以数组的形式,当这些 promise 都成功执行完成后才调用回调函数。segmentfault
var request1 = fetch('/users.json'); var request2 = fetch('/articles.json'); Promise.all([request1, request2]).then(function(results) { });
三、Promise.race是在全部的 promise 中只要有一个执行结束,它就会触发。数组
var req1 = new Promise(function(resolve, reject) { setTimeout(function() { resolve('First!'); }, 8000); }); var req2 = new Promise(function(resolve, reject) { setTimeout(function() { resolve('Second!'); }, 3000); }); Promise.race([req1, req2]).then(function(one) { console.log('Then: ', one); }).catch(function(one, two) { console.log('Catch: ', one); });
三、async 和 awaitpromise
如下内容摘自:边城的《理解 JavaScript 的 async/await》
原文地址: https://segmentfault.com/a/11...
(1)、介绍
async 是“异步”的简写,而 await 能够认为是 async wait 的简写。async 用于申明一个 function 是异步的,而 await 用于等待一个异步方法执行完成。await 只能出如今 async 函数中。服务器
(2)、async 起什么做用异步
这个问题的关键在于,async 函数是怎么处理它的返回值的!咱们固然但愿它能直接经过 return 语句返回咱们想要的值,可是若是真是这样,彷佛就没 await 什么事了。因此,写段代码来试试,看它到底会返回什么:async
async function testAsync() { return "hello async"; } const result = testAsync(); console.log(result);
输出的是一个 Promise 对象:函数
Promise { 'hello async' }
因此,async 函数返回的是一个 Promise 对象。async 函数(包含函数语句、函数表达式、Lambda表达式)会返回一个 Promise 对象,若是在函数中 return 一个直接量,async 会把这个直接量经过 Promise.resolve() 封装成 Promise 对象。使用.then() 链来处理这个 Promise 对象,post
testAsync().then(v => { console.log(v); // 输出 hello async });
如今回过头来想下,若是 async 函数没有返回值,它会返回 Promise.resolve(undefined)。
联想一下 Promise 的特色——无等待,因此在没有 await 的状况下执行 async 函数,它会当即执行,返回一个 Promise 对象,而且,毫不会阻塞后面的语句。这和普通返回 Promise 对象的函数并没有二致。
(3)、await 到底在等啥
通常来讲,都认为 await 是在等待一个 async 函数完成。不过按语法说明,await 等待的是一个表达式,这个表达式的计算结果是 Promise 对象或者其它值(换句话说,就是没有特殊限定)。
由于 async 函数返回一个 Promise 对象,因此 await 能够用于等待一个 async 函数的返回值——这也能够说是 await 在等 async 函数,但要清楚,它等的实际是一个返回值。注意到 await 不只仅用于等 Promise 对象,它能够等任意表达式的结果,因此,await 后面实际是能够接普通函数调用或者直接量的。因此下面这个示例彻底能够正确运行
function getSomething() { return "something"; } async function testAsync() { return Promise.resolve("hello async"); } async function test() { const v1 = await getSomething(); const v2 = await testAsync(); console.log(v1, v2); } test();
若是它等到的不是一个 Promise 对象,那 await 表达式的运算结果就是它等到的东西。
若是它等到的是一个 Promise 对象,await 就忙起来了,它会阻塞后面的代码,等着 Promise 对象 resolve,而后获得 resolve 的值,做为 await 表达式的运算结果。
看到上面的阻塞一词,心慌了吧……放心,这就是 await 必须用在 async 函数中的缘由。async 函数调用不会形成阻塞,它内部全部的阻塞都被封装在一个 Promise 对象中异步执行。
(5)、async/await 帮咱们干了啥
做个简单的比较:上面已经说明了 async 会将其后的函数(函数表达式或 Lambda)的返回值封装成一个 Promise 对象,而 await 会等待这个 Promise 完成,并将其 resolve 的结果返回出来。
如今举例,用 setTimeout 模拟耗时的异步操做,先来不用 async/await:
function takeLongTime() { return new Promise(resolve => { setTimeout(() => resolve("long_time_value"), 1000); }); } takeLongTime().then(v => { console.log("got", v); });
若是改用 async/await :
function takeLongTime() { return new Promise(resolve => { setTimeout(() => resolve("long_time_value"), 1000); }); } async function test() { const v = await takeLongTime(); console.log(v); } test();
眼尖的同窗已经发现 takeLongTime() 没有申明为 async。实际上,takeLongTime() 自己就是返回的 Promise 对象,加不加 async 结果都同样,若是没明白,请回过头再去看看上面的“async 起什么做用”。
(6)、对比以后,async/await的优点到底在哪?
async/await 的优点在于处理 then 链
单一的 Promise 链并不能发现 async/await 的优点,可是,若是须要处理由多个 Promise 组成的 then 链的时候,优点就能体现出来了(颇有意思,Promise 经过 then 链来解决多层回调的问题,如今又用 async/await 来进一步优化它)。
假设一个业务,分多个步骤完成,每一个步骤都是异步的,并且依赖于上一个步骤的结果。咱们仍然用 setTimeout 来模拟异步操做:
/** * 传入参数 n,表示这个函数执行的时间(毫秒) * 执行的结果是 n + 200,这个值将用于下一步骤 */ function takeLongTime(n) { return new Promise(resolve => { setTimeout(() => resolve(n + 200), n); }); } function step1(n) { console.log(`step1 with ${n}`); return takeLongTime(n); } function step2(n) { console.log(`step2 with ${n}`); return takeLongTime(n); } function step3(n) { console.log(`step3 with ${n}`); return takeLongTime(n); } 如今用 Promise 方式来实现这三个步骤的处理 function doIt() { console.time("doIt"); const time1 = 300; step1(time1) .then(time2 => step2(time2)) .then(time3 => step3(time3)) .then(result => { console.log(`result is ${result}`); console.timeEnd("doIt"); }); } doIt(); // c:\var\test>node --harmony_async_await . // step1 with 300 // step2 with 500 // step3 with 700 // result is 900 // doIt: 1507.251ms
输出结果 result 是 step3() 的参数 700 + 200 = 900。doIt() 顺序执行了三个步骤,一共用了 300 + 500 + 700 = 1500 毫秒,和 console.time()/console.timeEnd() 计算的结果一致。
若是用 async/await 来实现呢,会是这样
async function doIt() { console.time("doIt"); const time1 = 300; const time2 = await step1(time1); const time3 = await step2(time2); const result = await step3(time3); console.log(`result is ${result}`); console.timeEnd("doIt"); } doIt();
结果和以前的 Promise 实现是同样的,可是这个代码看起来是否是清晰得多,几乎跟同步代码同样
(7)、如今把业务要求改一下,仍然是三个步骤,但每个步骤都须要以前每一个步骤的结果。
function step1(n) { console.log(`step1 with ${n}`); return takeLongTime(n); } function step2(m, n) { console.log(`step2 with ${m} and ${n}`); return takeLongTime(m + n); } function step3(k, m, n) { console.log(`step3 with ${k}, ${m} and ${n}`); return takeLongTime(k + m + n); }
这回先用 async/await 来写:
async function doIt() { console.time("doIt"); const time1 = 300; const time2 = await step1(time1); const time3 = await step2(time1, time2); const result = await step3(time1, time2, time3); console.log(`result is ${result}`); console.timeEnd("doIt"); } doIt(); // c:\var\test>node --harmony_async_await . // step1 with 300 // step2 with 800 = 300 + 500 // step3 with 1800 = 300 + 500 + 1000 // result is 2000 // doIt: 2907.387ms
除了以为执行时间变长了以外,彷佛和以前的示例没啥区别啊!别急,认真想一想若是把它写成 Promise 方式实现会是什么样子?
function doIt() { console.time("doIt"); const time1 = 300; step1(time1) .then(time2 => { return step2(time1, time2) .then(time3 => [time1, time2, time3]); }) .then(times => { const [time1, time2, time3] = times; return step3(time1, time2, time3); }) .then(result => { console.log(`result is ${result}`); console.timeEnd("doIt"); }); } doIt();
有没有感受有点复杂的样子?那一堆参数处理,就是 Promise 方案的死穴—— 参数传递太麻烦了,看着就晕!