事件循环和任务队列
/eventLoop.png)
在 ES6 中,有一个新的概念建立在事件循环队列之上,叫作任务队列(job queue)。这个
概念给大家带来的最大影响可能是 Promise 的异步特性(参见第 3 章).
事件循环队列类似于一个游乐园游戏:玩过了一个游戏之后,你需要重新到队尾排队才能 再玩一次。而任务队列类似于玩过了游戏之后,插队接着继续玩.
回调导致的信任问题
关于回调
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
   |  function useless(callback){     return callback(); } useless(()=>{console.log("callback")}); (function fnA(){     console.log("fnA"); })()
  document.body.addEvetListener("mousemove",function(){      })
  const fs = require('fs'); fs.readFile('./title.json',(err,data)=>{     if(err) throw err;      })
 
  | 
 
交付第三方工具后控制反转
有时候 ajax(..)(也 就是你交付回调 continuation 的第三方)不是你编写的代码,也不在你的直接控制下。多 数情况下,它是某个第三方提供的工具。我们把这称为控制反转(inversion of control),也就是把自己程序一部分的执行控制交给某 个第三方。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
   |  ajax('..',function(..){      });
 
 
 
  analytics.trackPurchase(purchaseData, function(){          chargeCreditCard();     displayThankyouPage(); });
 
 
 
  | 
 
分析公司的开发者开发了一些实验性的代码,在某种情况下,会在五秒钟内每秒重试一次传入的回调函数,然后才会因超时而失败。
异步开发的难题
/asyncControl.png)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
   | 
 
 
  setTimeout(function() {      console.log('I execute first.');   setTimeout(function() {     console.log('I execute next.');     setTimeout(function() {       console.log('I execute last.');     }, 100);   }, 500); }, 1000);
 
  var fs = require('fs'); var completedTasks = 0; var tasks = []; var wordCounts = {}; var filesDir = './text'; function checkIfComplete() {   completedTasks++;   if (completedTasks == tasks.length) {     for (var index in wordCounts) {       console.log(index +': ' + wordCounts[index]);     }  } } function countWordsInText(text) {   var words = text     .toString()     .toLowerCase()     .split(/\W+/)     .sort();   for (var index in words) {     var word = words[index];     if (word) {       wordCounts[word] =          (wordCounts[word]) ? wordCounts[word] + 1 : 1;     }   } } fs.readdir(filesDir, function(err, files) {   if (err) throw err;   for(var index in files) {          var task = (function(file) {       return function() {         fs.readFile(file, function(err, text) {           if (err) throw err;           countWordsInText(text);                      checkIfComplete();         });       }     })(filesDir + '/' + files[index]);          tasks.push(task);   }   for(var task in tasks) {          tasks[task]();   } });
 
  | 
 
Promise
/promise.png)
- 特点
- promise异步是基于微任务的 ->回调太晚(等待时间太长)
 
- promise一旦决议,就永远保持这个状态
 
 
- 实用
- 链式回调 ->串行控制
 
- promise.race ->可以用来处理一直未决议的状况
 
- promise.all ->并行控制
 
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
   |  const promise = new Promise((resolve, reject) => {   resolve("Hattori");   setTimeout(()=> reject("Yoshi"), 500); }); promise.then(val => alert("Success: " + val))        .catch(e => alert("Error: " + e));
 
 
    upload() {     return new Promise(resolve => {       Taro.uploadFile({         url: 'https://kstack.test.muxixyz.com/api/v1/upload/image/',          filePath: this.state.avatar,         name: 'image',         formData: {                    },         header: {           token: Taro.getStorageSync('token')                    },         success(res) {           if (res.data) {             resolve(JSON.parse(res.data).data.url);           }         }       });     });   }   onSubmit() {     if (this.state.username == '') {       Taro.atMessage({         message: '标题不能为空',         type: 'warning'       });       return;     }     this.upload()       .then(url => {         Fetch(           'api/v1/user/info/',           {             username: this.state.username,             avatar: url           },           'POST'         ).then(ress => {           if (ress.message == 'OK')             Taro.showToast({ title: '修改成功', icon: 'success' });         });       })       .catch(err => {         console.error(err);         Taro.showToast({ title: '修改失败,请稍后重试', icon: 'fail' });       });   }
 
  | 
 
thenable
具有then()函数的对象,都是promise吗?不是。普通then()与promise产生的then的区别
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
   | var p = {     then: function(cb,errb){         cb(42);         errb("evil laugh");     } }; p.then(     function fulfilled(val){         console.log(val);      },     function rejected(err){         console.log(err);               } )
  | 
 
Promise与生成器结合
生成器函数是一个崭新的函数类型,它和标准的普通函数完全不同。生成器函数能生成一组值的序列,但是每组值的生产都是基于每次请求,并不同于标准函数那样立即生成。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
   |  function *IdGenerator(){   let id = 0;   while(true){     yield ++id;   } } const idIterator = IdGenerator(); const ninja1 = { id: idIterator.next().value }; assert(ninja1.id === 1, "First ninja has id 1");
 
  function getJSON(url){     return new Promise((resolve, reject) =>{         const request = new XMLHttpRequest();         request.open("GET", url);         request.send();         request.onload = function() {             try{                 if(this.status === 200){                     resolve(JSON.parse(this.response))                 }                              } catch(e){                 reject(e.message)             }         }              }) }  async(function*() {     try {         const ninjas = yield getJSON("data/ninjas.json");         const missions = yield getJSON(ninjas[0].missionsUrl);              }     catch(e) {              } });
  (async function () {     try {         const ninjas = await getJSON("data/ninjas.json");         const missions = await getJSON(missions[0].missionsUrl);         console.log(missions);     }     catch(e) {         console.log("Error: ", e);     } })()
 
  | 
 
使用生成器与promise结合,串行化异步操作似乎比promise.then().then()这种链式回调更美观,可是我没有看到实质上不得不用asnyc,await的原因。之后再看看……