Introduction to iterator generator Promise
1. Iterator
Iterator is a mechanism to implement unified traversal operations on different collections. Just deploy the Iterator interface to the data structure that needs to be traversed, and implement the traversal operation by calling the interface, or using the API that consumes the interface.
ES6 introduces an implicitly standardized interface for iterators. Many built-in data structures in Javascript, such as Array, Map, Set, String, TypedArray, function arguments objects, and NodeList objects all have the Iterator interface.
The Iterator interface is mainly used for for of. For of (it traverses the value
) is different from for in (it traverses the key).
const arr = [4, 3, 2, 1];
for (let v of arr) {
console.log(v); // 4 3 2 1
}
You can print an Array instance on the console to see that its prototype has a Symbol.iterator attribute (Symbol.iterator is actually the abbreviation of Symbol ('Symbol.iterator'). The attribute name is the Symbol type, which represents the unique and unique nature of this attribute. Overriding), it is the iterator function. When this function is executed, an iterator object will be returned, and there is a next() method under the object.
1.1. next() iteration
When the last element of the array is obtained, the iterator will not report done:true. At this time, next() needs to be called again to pass the value at the end of the array to get the completion signal done:true.
Normally, continuing to call the next method on an iterator object that has been iterated will continue to return {value: undefined, done: true} without reporting an error.
1.2. Implement custom traversed data
Customize the list data of traversing obj instead of obj
const obj = {
name: 'gg',
list: ['a', 'b', 'c', 'd', 'e'],
[Symbol.iterator]() {
let index = 0;
return {
next: () => {
if (index < this.list.length) {
const result = {
value: this.list[index], done: false };
index++;
return result;
} else return {
value: undefined, done: true };
}
};
}
};
for (let v of obj) {
console.log(v);
}
2. Generator
A generator is a special function and a new solution for asynchronous programming. Adding an * between function and the function name
returns an iterator object that can be used to call
the yield function code using the next() method.
function* gen() {
console.log('1');
yield 'a'; // 函数代码的分隔符
console.log('2');
yield 'b';
console.log('3');
yield 'c';
}
let iterator = gen(); // 返回的是一个迭代器对象 可以使用next() 方法调用
iterator.next(); // 1
iterator.next(); // 2
iterator.next(); // 3
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
The iterator object can be used to
output the code behind yield.
function* gen() {
yield 'a'; // 函数代码的分隔符
yield 'b';
yield 'c';
}
for (let v of gen()) {
console.log(v); // a b c
}
2.1. Generator passes parameters
The parameters passed by the next() method will be used as the return value of the previous yield
function* gen(arg) {
console.log(arg);
let one = yield 111;
console.log(one);
let two = yield 222;
console.log(two);
let three = yield 333;
console.log(three);
}
let iterator = gen('AAA');
console.log(iterator.next());
console.log(iterator.next('BBB'));
console.log(iterator.next('CCC'));
console.log(iterator.next('DDD'));
2.2. Case
2.2.1. Requirement 1
111 is output after 1s, 222 is output after 2s, and 333 is output after 3s. The total time is 6s
(1) Traditional writing method (callback hell)
setTimeout(() => {
console.log(111);
setTimeout(() => {
console.log(222);
setTimeout(() => {
console.log(333);
}, 3000);
}, 2000);
}, 1000);
(2) Generator writing method (elegant)
const one = () => {
setTimeout(() => {
console.log(111);
iterator.next();
}, 1000);
};
const two = () => {
setTimeout(() => {
console.log(222);
iterator.next();
}, 2000);
};
const three = () => {
setTimeout(() => {
console.log(333);
iterator.next();
}, 3000);
};
function* gen() {
yield one();
yield two();
yield three();
}
let iterator = gen();
iterator.next();
2.2.2. Requirement 2
Return order information through user information Return product information s
const getUser = () => {
setTimeout(() => {
let data = 'user';
iterator.next(data);
}, 1000);
};
const getOrder = () => {
setTimeout(() => {
let data = 'order';
iterator.next(data);
}, 1000);
};
const getGood = () => {
setTimeout(() => {
let data = 'good';
iterator.next(data);
}, 1000);
};
function* gen() {
let user = yield getUser();
console.log(user);
let order = yield getOrder();
console.log(order);
let good = yield getGood();
console.log(good);
}
let iterator = gen();
iterator.next();
3. Promise
Promise is a new solution for asynchronous programming introduced in ES6. Promise is a constructor that encapsulates asynchronous operations and can obtain the results of success.then() or failure.catch().
.then(a, b) can have two parameters, a means success and b means failure; b can also be omitted and use .catch() to return an error
const p = new Promise((resolve, reject) => {
setTimeout(() => {
// let data = 'data';
// resolve(data);
let err = 'gg';
if (err) {
reject(err);
}
}, 1000);
});
p.then(
result => {
console.log(result);
},
err => {
console.error(err);
}
).catch(err => {
console.error(err);
});
3.1. Reading a single file
(1) node error priority mechanism
const fs = require('fs');
fs.readFile('./1.txt', (err, data) => {
if (err) throw err;
console.log(data);
console.log(data.toString());
});
(2) Use promise encapsulation to read non-existent files and report errors.
const p = new Promise((resolve, reject) => {
fs.readFile('./2.txt', (err, data) => {
if (err) {
reject(err);
}
resolve(data);
});
});
p.then(data => {
console.log(data);
}).catch(err => {
console.error(err);
});
3.2. Ajax
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<script>
const xhr = new XMLHttpRequest();
xhr.open('get', 'http://ip-api.com/json/58.23.7.26?lang=zh-CN');
xhr.send();
xhr.onreadystatechange = () => {
if (xhr.readyState === 4) {
if (xhr.status >= 200 && xhr.status <= 300) {
console.log(xhr.response);
} else {
console.error(xhr.status);
}
}
};
</script>
</body>
</html>
3.3. Promise packaging
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<script>
const p = new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.open('get', 'http://ip-api.com/json/58.23.7.26?lang=zh-CN');
xhr.send();
xhr.onreadystatechange = () => {
if (xhr.readyState === 4) {
if (xhr.status >= 200 && xhr.status <= 300) {
resolve(xhr.response);
} else {
reject(xhr.status);
}
}
};
});
p.then(data => {
console.log(data);
}).catch(err => {
console.error(err);
});
</script>
</body>
</html>
3.4. then()
then can be called in a chain to solve the problem of callback hell.
If an empty or non-promise type object is returned, the status is success and the value is the value of the return (undefined if not returned)
const p = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('ok');
}, 1000);
});
const result = p
.then(data => {
console.log(data);
// 如果return一个空或非promise类型的对象,状态为成功,值为return的值(不return则为undefined)
// return 123;
})
.catch(err => {
console.error(err);
});
console.log(result);
return a promise object (the state returned by the object is the state of the then return value
const p = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('ok');
}, 1000);
});
const result = p
.then(data => {
console.log(data);
// 如果return一个空或非promise类型的对象,状态为成功,值为return的值(不return则为undefined)
// return 123;
// return 一个promise对象(对象返回的状态即为then返回值的状态)
return new Promise((resolve, reject) => {
resolve('ok');
});
})
.catch(err => {
console.error(err);
});
console.log(result);
3.5. Reading multiple files
fs.readFile('./1.txt', (err, data1) => {
fs.readFile('./2.txt', (err, data2) => {
fs.readFile('./3.txt', (err, data3) => {
console.log(data1 + data2 + data3);
});
});
});
new Promise((resolve, reject) => {
fs.readFile('./1.txt', (err, data) => {
resolve(data.toString());
});
})
.then(value => {
return new Promise((resolve, reject) => {
fs.readFile('./2.txt', (err, data) => {
resolve([value, data.toString()]);
});
});
})
.then(value => {
return new Promise((resolve, reject) => {
fs.readFile('./3.txt', (err, data) => {
value.push(data.toString());
resolve(value);
});
});
})
.then(value => {
console.log(value);
});