【generatory與iterator】的應用

沂蒙趙發表於2019-03-25

iterator 應用

iterator 迭代器 (迭代器有一個next方法,每次呼叫後都會返回 value,done兩個屬性)

// 類陣列 有長度 有索引 是個物件  能被迭代。 才能使用...擴充套件運算子

let obj = {0:1,1:2,2:3,length:3}
let arr = [...obj]
console.log(arr);//報錯 TypeError: obj is not iterable


// 給一個物件新增迭代器 , 可以使他被迭代
// 這個函式執行後返回的是一個迭代器
let obj = {0:1,1:2,2:3,length:3,[Symbol.iterator]:function(){
    let self = this;
    let index = 0
    return { // 迭代器
        next(){
            return {value:self[index],done:index++ === self.length}
        }
    }
}}
let ary = [...obj];
console.log(ary)//成功  返回[ 1, 2, 3 ]
複製程式碼

Generator 應用

// Generator生成器會配合yield 來使用 如果碰到yiled會暫停執行
function* read(){ 
    let a = yield 1; // 產出
    let b = yield a;
    let c = yield b;
  }
//Generator生成器返回的是iterator迭代器 迭代器有next方法 呼叫next可以返回 value和done
let it = read();
console.log(it)
console.log(it.next(50)) // 第一次next是不能傳遞引數
console.log(it.next(100))// 第二次傳參 執行之後會返回當前的value:100 和done:false
it.next(200) // 第三次傳參 執行之後會返回當前的value:200 和done:false
it.next(300) // 第四次傳參 執行之後會返回當前的value:300 和done:true  返回true 說明下邊沒有yield了
複製程式碼
使用 generator + co 實現 async + await
let fs = require('mz/fs')
function * read(){
    let result = yield fs.readFile('./a.txt','utf-8');
    let age = yield fs.readFile(result,'utf-8');
    let e =  yield [age];
    return e;
}
function co(it){
    return new Promise((resolve,reject)=>{
        function next(val){
            let {value,done} = it.next(val);
            if(done){return resolve(value);}
            // 如果不是promise 把他包裝成promise
            Promise.resolve(value).then(data=>{
                next(data);//如果done沒有返回true 說明還沒完成  遞迴繼續迭代 直到返回true為止
            },reject);
        }
        next();
    });
}
co(read()).then(data=>{
    console.log(data);
}).catch(e=>{
    console.log(e);
})
複製程式碼

相關文章