用各類方式實現同步for循環輸出(yeild, await...)

前段的功能愈來愈強大,如今實現同步的for循環輸出的方式也愈來愈多,咱們先看一個例子:html

forF();
function forF() {
  for (var i = 0; i < 3; i++) {
    setTimeout(function () {
      console.log(i);
    }, 1000)
  }
}
// 1s後輸出:3 3 3

相信你們對這個比較常見了,原理是由於var聲明的i爲forF的局部變量,setTimeout只是定時器,他暫時將內部函數掛起,等到一秒後執行,到那個時候,i已經變成了5。es6

那麼咱們的解決辦法有哪些呢?promise

先上一個es5之前的解決辦法:app

forF();
function forF() {
  for (var i = 0; i < 3; i++) {
    outF(i);
  }
}

function outF(i) {
  setTimeout(function () {
    console.log(i);
  }, 1000*i)
}
// 0 1 2

由於在循環中用了外部函數,那麼至關於建立了三個outF實例,由於i是基本變量,因此每一個實例的i都是不共享的,這裏要注意設置的定時器時間要1000*i;async

下面開始用es6的方法實現啦!
1.用塊做用域的let函數

forF();
function forF() {
  for (let i = 0; i < 3; i++) {
    setTimeout(function () {
      console.log(i);
    }, 1000*i)
  }
}

由於let是塊做用域的,對於setTimeout函數而言,每次循環都新建立一個i,每一個i不共享es5

2.await(實際上是es7的)
見代碼code

var sleep = function (time) {
    return new Promise(function (resolve, reject) {
        setTimeout(function () {
            resolve('ok');
        }, time);
    })
};
// // 用await實現循環輸出數字
async function awaitF() {
  for (var i = 0; i < 3; i++) {
    await sleep(1000);
    console.log(i)
  }
}
awaitF()
// 0 1 2

await顧名思義是等待,他接受一個promise對象,等待他相應而後才繼續執行。
注意用await的函數必須加async關鍵字
關於promise,推薦看大白話:https://www.cnblogs.com/lvdab...htm

3.yeild對象

function* countAppleSales () {
  for (var i = 0; i < 3; i++) {
    yield;
    console.log(i);
  }
}

var appleStore = countAppleSales(); // Generator { }
appleStore.next();
nextApp(appleStore);
function nextApp(appleStore) {
  setTimeout(function () {
    let done = appleStore.next().done;
    if (!done) {
      nextApp(appleStore);
    }
  }, 1000);
}

yield函數必須定義成function* 外部在調用此函數的時候必須用next()方法他纔會繼續執行到下個yeild那裏,因此這裏用遞歸去執行。
關於yeild的知識點百度也不少,可自行百度。


後續會更新,歡迎補充

相關文章
相關標籤/搜索