iterator与generator、重写promise

245 阅读2分钟

一、iterator:

基于有序连续的数据结构对象。

迭代器的实现:

1、迭代函数返回一个包含next方法的对象;

2、next方法返回一个包含value和done属性的对象

function setIterator(arr){
	var index=0
	return {
		next(){
			var obj={}
			if(index>arr.length){
				return {value:undefined,done:true}
			}else{
				return {value:arr[index++],done:false}
			}
		}
	}
}
var it=setIterator([1,3,4,5])
console.log(it.next());
console.log(it.next());
console.log(it.next());
console.log(it.next());

对象实现迭代器:

var obj = {
	a: 1,
	b: 2,
	c: 3,
	['gg'](){
		
	},
	[Symbol.iterator]:function(){
		var index = 0,
			entries = Object.entries(this);
			len=entries.length-1;
			console.log(len,entries);
		return {
			next() {
				var obj = {}
				if (index > len) {
					return { value: undefined, done: true }
				} else {
					return { value: entries[index++], done: false }
				}
			}
		}
	}
}
for (let s of obj) {
	console.log(s);
}

等价于:

var obj = {
	a: 1,
	b: 2,
	c: 3,
	['gg'](){
		
	}}
for (let s of Object.entries(obj)) {
    console.log(s);
}

隐式调用[Symbol.iterator]方法操作: 1、拓展运算符(...)

2、map set

3、for ...of Array.from

4、Promise.all / Promise.race

5、yield

二、generator生成器 ,

生成器函数:

返回值:生成器对象,

作用:阻止同步执行

yield:产出不同的内部值,然后暂停函数执行,并且记住上次执行的暂停点

function * test(){
	yield 'a'
	yield 'b'
	yield 'c'
}
let iter=test()
console.log(iter);
console.log(iter.next());

image.png

2-2,生成器函数的特点

1、通过返回的生成器调用next方法驱动执行,test内部的语句并不执行

function* test() {
	console.log('qige');
	console.log('wuzai');
}
let iter = test()

1、yield只能在生成器中使用,报语法错误:

function  test(){
	yield 'a'
}

2、在生成器内部,不能做赋值操作或者当实参,变量收不到值

function * test(){
 var value=yield 'a'
 console.log(value);//undefined
 foo(yield 'a')
 yield 'b'
}
function foo(a) {
	console.log(a);
}
let iter = test()

4、yield在表达式中不能单独存在,报语法错误:

function* test() {
	var value='qige'+ yield
	// var value='qige'+ (yield 'wuzai')
}

通过next传值:

function * test(){
	var a=yield 'a' +doo()
	 console.log(a);
	 var b=yield 'b'
	 console.log(b);
}
			
function doo(){
	return 111;
}
			
var iter=test()
console.log(iter.next());//a111
console.log(iter.next(11));//bb
console.log(iter.next(12));//undefined

通过上面的代码可以知道yield停止在赋值操作之前。

实现Promise

const PENDING = 'pending';
const Fulfilled = 'fulFilled';
const REJECTED = 'rejected';
export default class myPromise {
	constructor(executor) {
		this.status = PENDING;
		this.reason = undefined;
		this.value = undefined;
		this.fulFilledCallback = () => {};
		this.rejectedCallback =  () => {};
		try {
			executor(this.resolve, this.reject);
		} catch (e) {
			this.reject(e)
		}
	}
	resolve = (res) => {
		if (this.status === PENDING) {
			this.status = Fulfilled;
			this.value = res;
			this.fulFilledCallback()
		}
	}
	reject = (reason) => {
		if (this.status === PENDING) {
			this.status = REJECTED;
			this.reason = reason;
			this.rejectedCallback();
		}
	}
	static resolve(res) {
		return new myPromise((resovle, reject) => {
			resovle(res)
		})
	}
	static reject(res) {
		return new myPromise((resovle, reject) => {
			reject(res)
		})
	}
	catch (res) {
		return this.then(null, res)
	}
	then(onFulFilled, onRejected) {
		onFulFilled = typeof onFulFilled === 'function' ? onFulFilled : data => data;
		onRejected = typeof onRejected === 'function' ? onRejected : err => {
			throw err
		};
		let promise2 = new myPromise((resovle, reject) => {
			if (this.status === Fulfilled) {
				setTimeout(() => {
					let x = onFulFilled(this.value)
					resolvePromise(promise2, x)
				})
			}
			if (this.status === REJECTED) {			
				setTimeout(() => {
					try {
						let x = onRejected(this.reason)
						resolvePromise(promise2, x)
					} catch (e) {
						reject(e)
					}
				})
			}
			if (this.status === PENDING) {
				this.fulFilledCallback = () => {
					let x = onFulFilled(this.value)
					resolvePromise(promise2, x)
				}
				this.rejectedCallback = () => {
					let x = onRejected(this.reason)
					resolvePromise(promise2, x)
				}
			}
		})
		return promise2;
	}
}


function resolvePromise(promise2, x) {

	if (x instanceof myPromise) {
		let then = x.then;
		then.call(x, value => {
			setTimeout(() => {
				let v = getValueK(value);
				resolvePromise(promise2, v)
			})
		}, err => {
			promise2.reject(err)
		})
	} else {
		promise2.resolve(x)
	}
}

function getValueK(promise) {
	if (promise instanceof myPromise) {
		getValueK(promise.value)
	} else {
		return promise
	}
}