Written in the beginning

  • ES6 common but ignored methods series of articles, sorting out the author thinks that some daily development may use some methods, use skills and some application scenarios, details please see related content links, welcome to supplement exchange.

Related articles

  • Common but overlooked methods for ES6 (Destruct assignments and values first)
  • ES6 Common but ignored methods (second bullet functions, arrays, and objects)
  • ES6 common but ignored methods (third bullet Symbol, Set, and Map)
  • ES6 commonly used but overlooked methods (fourth bullet Proxy and Reflect)
  • Common but ignored methods for ES6 (Generator 6)
  • ES6 Common but ignored methods (async)
  • ES6 Common but ignored methods (eighth bullet Class)
  • ES6 common but ignored methods (Module 9)
  • Common but ignored methods of ES6 (Development specification of the Tenth Bullet Project)
  • ES6 common but ignored method (eleventh bullet Decorator)
  • Common but overlooked approaches to ES6 (End game – Latest Proposal)

Promise

  • ES6-Promise
  • Take a look at the most fully written implementation of ES6 Promise
  • PromiseIs a solution to asynchronous programming that is more reasonable and powerful than the traditional solution of callback functions and events.

The characteristics of

  1. The status of an object is not affected. There are three states:pending(In progress),fulfilled(Successfully) andrejected(Failed). Only the result of an asynchronous operation can determine the current state, and no other operation can change the state.
  2. Once the state changes, it never changes again, and you can get this result at any time. PromiseThe state of an object can change in only two ways: frompendingintofulfilledAnd from thependingintorejected.

use

  • PromiseThe object is a constructor, used to generatePromiseInstance. The constructor takes as an argument a function whose two arguments areresolveandreject.resolveWhat the function does is it takesPromiseThe state of the object changes from Incomplete to Succeeded (that is, frompendingintoresolved);rejectWhat the function does is it takesPromiseThe state of the object changes from incomplete to Failed (that is, frompendingintorejected).
Const promise = new promise (function(resolve, reject) {resolve(value); } else { reject(error); }});Copy the code
  • PromiseAfter the instance is generated, you can usethenMethods specified separatelyresolvedState andrejectedState callback function. A method can take two callback functions as arguments. The first callback function isPromiseThe object status becomesresolvedThe second callback function is calledPromiseThe object status becomesrejectedWhen the call. The second function is optional and does not have to be provided.
promise.then(function(value) {
  // success
}, function(error) {
  // failure
});
Copy the code
  • PromiseIt will be executed immediately after being created. thenMethod that will not execute until all synchronization tasks in the current script have been completed.JavaScript event loop mechanism

Promise.resolve()

  • Convert an existing object toPromiseObject.
  • Different parameters:
    1. The parameter is aPromiseInstance, which is returned directly.
    2. The parameter is athenableObject (thenableObject refers to havingthenMethod) to convert the object toPromiseObject, and execute immediatelythenableThe object’sthenMethods.
    let thenable = { then: function(resolve, reject) { resolve(42); }}; let p1 = Promise.resolve(thenable); p1.then(function(value) { console.log(value); / / 42});Copy the code
    1. Parameter does not havethenMethod object, or not object at all, returns a new onePromiseObject in the state ofresolved.
    const p = Promise.resolve('detanx');
    
    p.then(function (s){
      console.log(s)
    });
    // detanx
    Copy the code
    1. Returns one without any argumentsresolvedThe state of thePromiseObject.immediatelyresolve()thePromiseObject in this “event loop” (event loop), rather than at the beginning of the next “event loop”.
    setTimeout(function () {
      console.log('three');
    }, 0);
    
    Promise.resolve().then(function () {
      console.log('two');
    });
    
    console.log('one');
    
    // one
    // two
    // three
    Copy the code

Promise.reject()

  • Promise.reject(reason)The method also returns a new onePromiseInstance, whose state isrejected.Promise.reject()The parameters of the method are left as they arerejectBecomes the parameter of the subsequent method.To this point andPromise.resolveMethods are inconsistent.
Const thenable = {then(resolve, reject) {reject(' error '); }}; Promise.reject(thenable) .catch(e => { console.log(e === thenable) }) // trueCopy the code

Promise.prototype.catch()

  • Promise.prototype.catch()Method is.then(null, rejection)or.then(undefined, rejection)Alias for thehandwrittenPromiseThe method is implemented), which specifies the callback function in case of an error.
// const promise = new promise (function(resolve, reject) {try {throw new Error('test'); } catch(e) { reject(e); }}); promise.catch(function(error) { console.log(error); }); // const promise = new promise (resolve, reject) {reject(new Error('test')); }); promise.catch(function(error) { console.log(error); });Copy the code
  • ifPromiseThe state has becomeresolvedThrowing an error is invalid.
const promise = new Promise(function(resolve, reject) {
  resolve('ok');
  throw new Error('test');
});
promise
  .then(function(value) { console.log(value) })
  .catch(function(error) { console.log(error) });
// ok
Copy the code
  • PromiseObject errors are “bubbling” and are passed backwards until they are caught.
getJSON('/post/1.json').then(function(post) { return getJSON(post.commentURL); }). Then (function(comments) {// some code}). Catch (function(error) {//Copy the code
  • Generally not inthen()Method defined inRejectThe state callback function (i.ethenThe second argument) is always usedcatchMethods.
// bad
promise
  .then(function(data) {
    // success
  }, function(err) {
    // error
  });

// good
promise
  .then(function(data) { //cb
    // success
  })
  .catch(function(err) {
    // error
  });
Copy the code
  • With the traditionaltry/catchThe code block is different if not usedcatch()Method specifies the error handling callback function,PromiseAn error thrown by an object is not passed to the outer code, that is, there is no response.
Const someAsyncThing = function() {return new Promise(resolve(x + 2)); }); }; someAsyncThing().then(function() { console.log('everything is great'); }); setTimeout(() => { console.log(123) }, 2000); // Uncaught (in promise) ReferenceError: x is not defined // 123Copy the code

Promise.prototype.finally()

  • finally()Method is used to specify whetherPromiseThe operation to be performed in the final state of the object.The method isES2018Introduce standard.
Promise. Then (result = > {...}). The catch (error = > {...}), finally (() = > {the console. The log (' detanx '); }); // 'detanx'Copy the code
  • finallyThe method’s callback function does not take any arguments, which means there is no way to know the previous onePromiseIs the statefulfilledorrejected. The operations within a method should be state independent and not dependent onPromiseThe execution result of.finallyThe method always returns the original value.
/ / implementation Promise. Prototype. Finally = function (the callback) {let P = this. Constructor; return this.then( value => P.resolve(callback()).then(() => value), reason => P.resolve(callback()).then(() => { throw reason }) ); }; // use undefined promise.resolve (2). Then (() => {}, () => {}) // use undefined promise.reject ().reject() => {}). Then () => {}, () = > {}) / / reject a value of 3 Promise. Reject (3) finally (() = > {})Copy the code

Promise.all(), promise.race () and promise.allSettled ()

  • The same
    1. Methods are used to combine multiplePromiseInstance, wrapped into a new onePromiseInstance.
    2. Promise.all()All instances return yesfulfilledAnd when thePromise.allSettled()All return values are arrays.
  • The difference between
    1. Sometimes we don’t care about the results of asynchronous operations, only whether they end or not. At this time,Promise.allSettled()The method is very useful. Without this method, it would be a hassle to make sure everything was done.Promise.all()Methods do not do this.
    const urls = [ /* ... */ ]; const requests = urls.map(x => fetch(x)); try { await Promise.all(requests); Console. log(' All requests were successful. '); } catch {console.log(' At least one request failed, others may not be finished. '); }Copy the code
    1. Promise.all()One of all instances isrejected.pThe state of theta becomes thetarejectedAt this point, the first is returnedrejectThe value of the instance of.Promise.allSettled()In the instancefulfilledWhen, the object hasvalueProperties,rejectedFrom time to tomereasonProperty corresponding to the return values of the two states.
    const resolved = Promise.resolve(42);
    const rejected = Promise.reject(-1);
    
    const allSettledPromise = Promise.allSettled([resolved, rejected]);
    
    allSettledPromise.then(function (results) {
      console.log(results);
    });
    // [
    //    { status: 'fulfilled', value: 42 },
    //    { status: 'rejected', reason: -1 }
    // ]
    Copy the code
    1. If it’s a parameterPromiseExample, you define it yourselfcatchMethod, then once it isrejected, does not triggerPromise.all()thecatchMethods. If the instance does not have its owncatchMethod is calledPromise.all()thecatchMethods.
    const p1 = new Promise((resolve, reject) => { resolve('hello'); }) .then(result => result) .catch(e => e); Const p2 = new Promise((resolve, reject) => {throw new Error(' Error '); }). Then (result => result) => / Promise.all([p1, p2]) .then(result => console.log(result)) .catch(e => console.log(e)); // ["hello", Error: Error] => // remove p2 catch // // Error: ErrorCopy the code
    1. Promise.race()As long as one instance changes the state first, the state changes. The one who changed firstPromiseThe return value of the instance is passed to the callback function.
    const p = Promise.race([1, new Promise(function (resolve, reject) { setTimeout(() => reject(new Error('request timeout')), 5000) }) ]); p .then(console.log) .catch(console.error); / / 1Copy the code

The Iterator and for… Of circulation

  • ES6 Iterator and for… Of circulation
  • It is an interface that provides a unified access mechanism for various data structures. The Iterator interface can be deployed on any data structure to complete traversal (that is, processing all members of the data structure in turn).
  • IteratorThe role of:
    1. To provide a unified and simple access interface for various data structures;
    2. To enable the members of a data structure to be arranged in some order;
    3. New traversal commandfor... ofCycle,IteratorInterface mainly forfor... ofConsumption.
  • Traversal process:
    1. Creates a pointer object that points to the start of the current data structure. That is, the traverser object is essentially a pointer object.
    2. The first time a pointer object is callednextMethod to point to the first member of a data structure.
    3. The second call to the pointer objectnextMethod, which points to the second member of the data structure.
    4. That constantly calls the pointer objectnextMethod until it points to the end of the data structure.
    • Every callnextMethod, which returns information about the current member of the data structure (returns a containvalueanddoneObject with two properties.valueProperty is the value of the current member,doneProperty is a Boolean value indicating whether the traversal is complete.
    var it = makeIterator(['a', 'b']); it.next() // { value: "a", done: false } it.next() // { value: "b", done: false } it.next() // { value: undefined, done: true } function makeIterator(array) { var nextIndex = 0; return { next: function() { return nextIndex < array.length ? {value: array[nextIndex++], done: false} : {value: undefined, done: true}; }}; }Copy the code
    • For the traverser object,done: falseandvalue: undefinedAttributes can be omitted.
    Function makeIterator(array) {var nextIndex = 0; return { next: function() { return nextIndex < array.length ? {value: array[nextIndex++]} : {done: true}; }}; }Copy the code
  • useTypeScriptThe writing of
    • Traverser interface (可迭代), pointer object (Iterator) andnextThe specification of the method return value can be described as follows.
    interface Iterable { [Symbol.iterator]() : Iterator, } interface Iterator { next(value? : any) : IterationResult, } interface IterationResult { value: any, done: boolean, }Copy the code

The default Iterator interface

  • When usingfor... ofWhen a loop iterates over some data structure, the loop automatically looks for itIteratorInterface. The defaultIteratorThe interface is deployed in the data structureSymbol.iteratorProperty, or a data structure that hasSymbol.iteratorProperties can be considered “traversable” (可迭代).
const obj = { [Symbol.iterator] : function () { return { next: function () { return { value: 1, done: true }; }}; }};Copy the code
  • The native hasIteratorInterface data structure:Array,Map,Set,String,TypedArray, the function ofargumentsObjects,NodeListobject.
  • If an object is to be able to befor... ofCircularly calledIteratorInterface, must be inSymbol.iteratorDeploys the traverser generation method on the property of the
class RangeIterator { constructor(start, stop) { this.value = start; this.stop = stop; } [Symbol.iterator]() { return this; } next() { var value = this.value; if (value < this.stop) { this.value++; return {done: false, value: value}; } return {done: true, value: undefined}; } } function range(start, stop) { return new RangeIterator(start, stop); } for (var value of range(0, 3)) { console.log(value); // 0, 1, 2}Copy the code
  • The array-like object calls the array’sSymbol.iteratorTraversal; Common objects deploy arraysSymbol.iteratorMethod, and no effect.
Iterable = {0: 'a', 1: 'b', 2: 'c', length: 3, [symbol.iterator]: array. prototype[symbol.iterator]}; for (let item of iterable) { console.log(item); / / 'a', 'b', 'c'} / / ordinary objects, the subscript is not digital let iterable = {a: 'a', b: 'b', c: 'c', length: 3, [Symbol. The iterator] : Array.prototype[Symbol.iterator] }; for (let item of iterable) { console.log(item); // undefined, undefined, undefined }Copy the code
  • If the symbol. iterator method corresponds to anything other than an ergoer generator (that is, an ergoer object is returned), the interpretation engine will report an error.
var obj = {};
obj[Symbol.iterator] = () => 1;
[...obj] // TypeError: [] is not a function
Copy the code

The context in which the Iterator interface is called

  1. Deconstruction assignment
    • An array andSetIs called by default when the structure is destructively assignedSymbol.iteratorMethods.
  2. Extended operator
    • Extended operator (.) will also call the defaultIteratorInterface.
  3. yield*
    • yield*This is followed by a traversable structure, which calls the traverser interface of that structure.
  4. other
    • for... of,Array.from(),Map(), Set().WeakMap().WeakSet()(e.g.,new Map([['a',1],['b',2]])),Promise.all(),Promise.race().

Iterator object return() and throw()

  • The traverser object in addition to havingnextMethod can also havereturnMethods andthrowMethods. If you write your own traverser object generator function, thennextMethods must be deployed,returnMethods andthrowWhether or not a method is deployed is optional.
  • for... ofThe loop exits prematurely (usually because of an error, or there isbreakStatement), will be calledreturnMethods. If an object needs to clean up or release resources before completing traversal, it can be deployedreturnMethods.
function readLinesSync(file) { return { [Symbol.iterator]() { return { next() { return { done: false }; }, return() { file.close(); return { done: true }; }}; }}; } for (let line of readLinesSync(fileName)) {console.log(line); break; } for (let line of readLinesSync(fileName)) {console.log(line); throw new Error(); }Copy the code
  • throwThe main method is to cooperateGeneratorFunction, which we’ll see in the next pop.

for… Of circulation

  • As a unified way to traverse all data structures.
  • Compare with other traversals
    1. for... ofWill correctly identify32UTF-16Characters. With withfor... inSame concise syntax, but nofor... inThose flaws. Different from theforEachMethod, it can be withbreak,continueandreturnUse together.
    for (let x of 'a\uD83D\uDC0A') {
      console.log(x);
    }
    // 'a'
    // '\uD83D\uDC0A'
    Copy the code
    1. forEachCan’t jump out halfwayforEachCycle,breakCommand orreturnOrders are not effective.
    2. for... inLooping disadvantages, one is that the array’s key name is a number, butfor... inThe loop has a string as its key name.0“,”1“,”2“And so on. The second isfor... inThe loop iterates not only over numeric key names, but also over other manually added keys, and even keys on the prototype chain. And finally in some cases,for... inThe loop iterates over the key names in any order.for... inLoops are designed primarily for traversing objects, not for traversing groups of numbers.
  • Other types of data can be converted using other techniquesIteratorInterface data structure reusefor... ofI’m going to iterate.
    1. object
    • useObject.keysThe getKey () method generates an array of the object’s key names and then iterates through the array.
    for (var key of Object.keys(someObject)) {
      console.log(key + ': ' + someObject[key]);
    }
    Copy the code
    • useGeneratorThe function rewraps the object.
    function* entries(obj) {
      for (let key of Object.keys(obj)) {
        yield [key, obj[key]];
      }
    }
    
    for (let [key, value] of entries(obj)) {
      console.log(key, '->', value);
    }
    // a -> 1
    // b -> 2
    // c -> 3
    Copy the code
    1. An array-like object but does not have oneIteratorinterface
    • useArray.fromMethod to turn it into an array.
    let arrayLike = { length: 2, 0: 'a', 1: 'b' }; For (let x of arrayLike) {console.log(x); } for (let x of array. from(arrayLike)) {console.log(x); }Copy the code