Promises are executed in parallel and sequentially
Array. The prototype. Includes () method
Returns a Boolean value to determine whether an array contains a specified value
const arr = [1, 3, 5, 2, '8', NaN, -0]
arr.includes(1) // true
arr.includes(NaN) // true
arr.includes(+0) // true
Copy the code
IndexOf () returns the first index in the array where a given element can be found, or -1 if none exists
Internally, the strict equality operator (===) is used for judgment, resulting in a misjudgment of NaN
[NaN].indexOf(NaN)// -1
Copy the code
The find method on instances of the find() and findIndex() arrays, used to find the first eligible array member
[1, 4, -5, 10].find((n) => n < 0) // -5
[1, 5, 10, 15].findIndex(function(value) {
return value > 9;
}) // 2
[NaN].findIndex(y => Object.is(NaN, y)) // 0
Copy the code
Array.prototype.flat()
The array is recursively traversed at a specified depth, and all elements are merged with the elements in the traversed subarray into a new array
NewArray = arr.flat(depth) // depth specifies the structure depth to extract the nested array, Default value is 1 const numbers1 = [1, 2, [3, 4, [5, 6]] console.log(numbers1.flat())// [1, 2, 3, 4, [5, 6]] console.log(numbers2.flat(2))// [1, 2, 3, 4, 5, 6]Copy the code
Promise uses three major techniques to solve callback hell:
- Callback function deferred binding: Callback functions are not declared directly, but are passed in via the later THEN method, that is, deferred
- Return value through.
- Error bubbling: Handle success and failure separately
readFilePromise('1.json').then(data => { return readFilePromise('2.json'); }).then(data => { return readFilePromise('3.json'); }).then(data => { return readFilePromise('4.json'); }). Catch (err => {// XXX}); Solve errors in judgment and increase code clutter in each taskCopy the code
Once there is an error in the PENDING Promise state, the state will inevitably change to failure, and then the onRejected function will be executed. The onRejected function will throw an error, and the new Promise state will change to failure. The new Promise state changes to onRejected…… if it fails This continues until the error is caught and the drop is stopped. This is the Promise error bubble mechanism
promise
A Promise is an object that represents the final completion or failure of an asynchronous operation. Because its then, catch, and finally methods return a new Promise, it allows us to make chained calls, solving the traditional callback hell problem
ES6 specifies that a Promise object is a constructor that generates a Promise instance
Promise is a constructor with familiar methods all, Reject, and resolve on its own, and equally familiar methods like THEN and catch on its prototype. If you use a Promise new, you must have then and catch methods
The Promise constructor takes a function as an argument, resolve and reject, that represents the successful and unsuccessful callback of the asynchronous operation
Var p = new Promise(function (resolve, reject) {setTimeout(function () {console.log(' done '); Resolve (' data '); }, 2000); }); // After 2 seconds, print "Execution complete" and call the resolve methodCopy the code
Tips: Just new an object, without calling it, the function I passed in is already executed. This is a detail to note. So promises are usually wrapped in a function that you can run if you need to
function runAsync(){ var p = new Promise(function(resolve, Reject){// do something asynchronous setTimeout(function(){console.log(' done '); Resolve (' data '); }, 2000); }); return p; } runAsync()Copy the code
// Define a Promise directly in the script file. The first argument to its constructor is immediately executed: Const p1 = new Promise(r => console.log(' print now ')) // So to control when it executes, we can wrap it with a function that we call whenever we need it to execute: Function runP1() {const p1 = new Promise(r => console.log(' print now ')) return p1} runP1() // only when this function is calledCopy the code
The essence of a Promise is a finite state machine with three states:
- PENDING (waiting)
- FULFILLED (successful)
- REJECTED (failure)
For a Promise, the state change is irreversible, that is, after the waiting state changes to another state, it cannot be changed again
The characteristics of
- Once a Promise status changes, it cannot be changed
const promise = new Promise((resolve, reject) => { resolve("success1"); reject("error"); resolve("success2"); }); promise .then(res => { console.log("then: ", res); }).catch(err => { console.log("catch: ", err); }) // Result: "then: success1" // Indicates that resolve or reject in the constructor is valid only on the first execution, and multiple calls have no effectCopy the code
-
.then and.catch both return a new Promise
-
Catch can catch errors that are not caught by the upper layer, no matter where it is connected, okay
const promise = new Promise((resolve, reject) => { reject("error"); resolve("success2"); }); promise .then(res => { console.log("then1: ", res); }).then(res => { console.log("then2: ", res); }).catch(err => { console.log("catch: ", err); }).then(res => { console.log("then3: ", res); }) // Result: "catch: ""error" "then3:" undefinedCopy the code
- In a Promise, any value returned that is not a Promise is wrapped as a Promise object. For example, return 2 is wrapped as return promise.resolve (2).
Promise.resolve(1) .then(res => { console.log(res); return 2; }) .catch(err => { return 3; }) .then(res => { console.log(res); }); The res in resolve(1) then returns the value of the first then, not the catch. And return 2 is wrapped as resolve(2) // tips: What happens if promise.resolve (1) is changed to promise.reject (1)? Print 1 and 3, because reject(1) is a catch, and the res in the second then returns the catchCopy the code
- A Promise’s.then or.catch can be called multiple times, but if the internal state of the Promise changes and a value is given, that value will be returned each time a.then or.catch is called
const promise = new Promise((resolve, reject) => { setTimeout(() => { console.log('timer') resolve('success') }, 1000) }) const start = Date.now(); promise.then(res => { console.log(res, Date.now() - start) }) promise.then(res => { console.log(res, Date.now() -start)}) // result: 'timer' 'success' 1001 'success' 1002Copy the code
- The value returned by. Then or. Catch cannot be the promise itself, otherwise an infinite loop will occur
const promise = Promise.resolve().then(() => { return promise; }) promise.catch(console.err) // Result: Uncaught (in promise) TypeError: Chaining cycle detected for promise #< promise >Copy the code
- The parameters of.then or.catch are expected to be functions, and pass-through occurs when passing non-functions
Promise.resolve(1).then(2)// numeric type.then (promise.resolve (3))// object type.then (console.log) // Result :1Copy the code
- The. Then method takes two arguments, the first for the successful function and the second for the failed function, and sometimes you can think of catch as a shorthand for the second argument
Promise.reject('err!!! ') .then((res) => { console.log('success', res) }, (err) => { console.log('error', (err)}). Catch err = > {the console. The log (' catch 'err)}) / / results:' error 'error!!! 'Copy the code
But here’s another case:
Promise.resolve() .then(function success (res) { throw new Error('error!!! ') }, function fail1 (err) { console.log('fail1', err) }).catch(function fail2 (err) { console.log('fail2', Fail2 Error: Error!! At success // Since the Promise calls resolve(), then() should execute success(), but success() throws an error that is caught by a later catch(), not by fail1Copy the code
- .then or. Catch returns an error object that does not throw an error, so it will not be caught by subsequent.catches
Promise.resolve().then(() => { return new Error('error!!! ') }).then(res => { console.log("then: ", res) }).catch(err => { console.log("catch: ", err)}) // Return any non-promise value wrapped as a Promise object, so return new Error(' Error!!! Resolve (new Error(' Error!!! Then: "then: ""Error: Error!!" If you throw an Error, use either of the following 👇 : return promise.reject (new Error(' Error! ')); // or throw new Error('error!!! ')Copy the code
The realization of alternating repeat light traffic lights
function red() {
console.log("red");
}
function green() {
console.log("green");
}
function yellow() {
console.log("yellow");
}
const light = function (timer, cb) {
return new Promise(resolve => {
setTimeout(() => {
cb()
resolve()
}, timer)
})
}
const step = function () {
Promise.resolve().then(() => {
return light(3000, red)
}).then(() => {
return light(2000, green)
}).then(() => {
return light(1000, yellow)
}).then(() => {
return step()
})
}
step();
Copy the code
Promise.race()
The function is to receive a set of asynchronous tasks, and then execute the asynchronous tasks in parallel, keeping only the results of the first completed asynchronous operation. The other methods are still executed, but the execution results are discarded
Promise.all()
Receive a set of asynchronous tasks and execute them in parallel, retaining only the results of the first completed asynchronous operation. The other methods still execute, but the results are discarded
Core functions:
- Resolve is passed as an empty iterable.
- If one of the arguments fails, the promise object returned by promise.all fails.
- In any case, promise.all returns an array as the result of the completion state of the Promise
// The following function passes in a value x, Function runAsync (x) {const p = new Promise(r => setTimeout(() => r(x, console.log(x))), 1000)) return p} // Promise.all([runAsync(1), runAsync(2), runAsync(3)]).then(res => console.log(res)) After the interval of one second, the console prints 1, 2, 3, and an array [1, 2, 3] simultaneously. With all, multiple asynchronous operations can be performed in parallel. '// promise.all (). Then () returns the same array order as promise.all () received And the array order in this result is the same as the array order received by promise.all ()!!Copy the code
/ / case: const wait = ms => new Promise((resolve, reject) => { setTimeout(() => { console.log(`wait ${ms}ms`) resolve() }, Ms)}) const PA = Promise. All ([wait(3000), wait(1000), wait(2000)]) Wait 1000ms wait 2000ms wait 3000ms //async-await operation: const wait = ms => new Promise((resolve, reject) => { setTimeout(() => { console.log(`wait ${ms}ms`) resolve() }, ms) }) ; (async () => {await promise.all ([wait(3000), wait(1000), wait(2000)]) Wait 1000ms wait 2000ms wait 3000ms}) const arr = [1, 2, 3] arr.reduce((p, x) => { return p.then(() => { return new Promise(r => { setTimeout(() => r(console.log(x)), 1000) }) }) }, Promise.resolve()) // const arr = [1, 2, 3] arr.reduce((p, x) => p.then(() => new Promise(r => setTimeout(() => r(console.log(x)), 1000))), Promise.resolve()) // If the array passed by all and race contains an asynchronous task that throws an exception, only the first error thrown will be caught, either by the second argument to then or by a subsequent catch; This does not affect the execution of other asynchronous tasks in the arrayCopy the code
If the array passed by all and race contains an asynchronous task that throws an exception, only the first error thrown will be caught, either by the second argument to then or by a subsequent catch. This does not affect the execution of other asynchronous tasks in the array
How do I guarantee that if one request is abnormal in promise. all, I can still get the return value of another successful request?
Controlling concurrent requests
Function Request (urls,maxNumber,callback), makes concurrent web requests based on the URLS in the urls array,maxNumber of concurrent requests, and invokes the callback function when all requests are complete
Scenario: Promises Array each object is an HTTP request, or each object contains complex call handling. And there are hundreds of thousands of them. Make hundreds of thousands of HTTP requests in a fraction of a second (a lack of TCP connections can cause waiting), or run out of memory by piling up countless call stacks. Consider concurrency restrictions on promise.all
Promise.all concurrency limit means that the number of concurrent promises executed at any time is fixed, and the final execution result remains the same as the original promise. all
Promises are not executed by calling promise.all, but by instantiating the promise object. With this in mind, the only way to achieve concurrency limits is to start with promise instantiation, which gives control of generating promises arrays to concurrency control logic
function asyncPool(poolLimit, array, iteratorFn) { let i = 0; const ret = [], executing = []; const enqueue = function () { if (i === array.length) {return Promise.resolve(); } const item = array[i++]; const item = array[i++]; const p = Promise.resolve().then(() => iteratorFn(item, array)); ret.push(p); Const e = p.chen (() => executing.splice(e), 1)); // Create a promise array. // Insert a executing number to say that a promise is executing. Push (e); // Use promise.rece, whenever the number of promises in the executing array is lower than poolLimit, instantiate the new Promise and execute let r = promise.resolve (); if (executing.length >= poolLimit) {r = Promise.race(executing); } // recurse until array return r.hen (() => enqueue()); }; return enqueue().then(() => Promise.all(ret)); }Copy the code
Number in process, number that has been processed
Since it’s a promise with recursion, it’s not easy to mark the execution order in code comments, but the general logic can be summarized as follows: Starting with the first element of array, initialize the promise object and keep the executing promise in a executing array until poolLimt is reached
Race: Executing a Promise. In executing a Promise, you need to initialize a Promise and place it in a executing state
When all promises have been executed, a call to promise.all returns
The realization of the Promise
How it works: It’s basically a publishing subscriber model
- The constructor takes an executor function and executes it immediately on new Promise()
- Then collect dependencies, collecting callback functions into a success/failure queue
- The resolve/reject function is called in the executor function
- The resolve/reject function is notified to trigger a callback in the queue when called
const isFunction = variable =>typeof variable === 'function'; Const PENDING = 'PENDING '; const FULFILLED = 'fulfilled'; const REJECTED = 'rejected'; Class MyPromise {// constructor(handle: Function) {try {handle(this._resolve, this._reject); } catch (err) { this._reject(err); }} // state depressing // private _status: string = pending; / / stored value to then return to the private _value: string | undefined = undefined; Private _rejectedQueues: any = []; Private _implemented queues: any = []; Private _resolve = val => {const run = () => {if (this._status! == PENDING) return; this._status = FULFILLED; Const rundepressing = value => {let cb; while ((cb = this._fulfilledQueues.shift())) { cb(value); }}; Const runRejected = error => {let cb; while ((cb = this._rejectedQueues.shift())) { cb(error); }}; /* * If resolve is a Promise, */ If (val instanceof MyPromise) {val.then(value => {if (val instanceof MyPromise) {val.then(value => { this._value = value; runFulfilled(value); }, err => { this._value = err; runRejected(err); }); } else { this._value = val; runFulfilled(val); }}; // Call setTimeout(run) asynchronously; }; Private _reject = err => {if (this._status! == PENDING) return; Const run = () => {this._status = REJECTED; this._value = err; let cb; while ((cb = this._rejectedQueues.shift())) { cb(err); }}; // To support synchronous promises, call setTimeout(run) asynchronously; }; // This is a big pity. , onRejected?) { const { _value, _status } = this; // Return a new Promise object. OnRejectedNext) => {// Encapsulate a successful function const pity => {try {if (! isFunction(onFulfilled)) { onFulfilledNext(value); } else { const res = onFulfilled(value); If (res instanceof MyPromise) {// If (res instanceof MyPromise) {// If (res instanceof MyPromise) {// If (res instanceof MyPromise) {// If (res instanceof MyPromise) {// If (res instanceof MyPromise) { } else {// If the result is not returned, the next then callback function is passed as an argument, and the next THEN callback function is executed immediately onledNext (res); }}} Catch (err) {// If the function fails, the state of the new Promise object is failed onRejectedNext(err); }}; Const rejected = error => {try {if (! isFunction(onRejected)) { onRejectedNext(error); } else { const res = onRejected(error); If (res instanceof MyPromise) {// If (res instanceof MyPromise) {// If (res instanceof MyPromise) {// If (res instanceof MyPromise) {// If (res instanceof MyPromise) {// If (res instanceof MyPromise) { } else {// If the result is not returned, the next then callback function is passed as an argument, and the next THEN callback function is executed immediately onledNext (res); }}} Catch (err) {// If the function fails, the state of the new Promise object is failed onRejectedNext(err); }}; // When the state is pending, add the then call-back function to the queue to wait for execution. this._rejectedQueues.push(rejected); break; // If the status has changed, execute the corresponding callback function immediately. Case depressing: depressing (_value); break; case REJECTED: rejected(_value); break; }}); } // catch method catch(onRejected) {returnthis. Then (undefined, onRejected); } // finally method finally(cb) {returnthis.then(value => mypromise.resolve (cb()).then(() => value), reason => MyPromise.resolve(cb()).then(() => { throw reason; })); If (value instanceof MyPromise) return value; if (value instanceof MyPromise) return value; returnnew MyPromise(resolve => resolve(value)); } // static reject(value) {returnNew MyPromise((resolve, reject) => reject(value)); } static all(list) {returnNew MyPromise((resolve, reject) => {let values = []; let count = 0; For (let [I, p] of list.entries()) {// array parameters if not MyPromise instance, Mypromise.resolve this.resolve(p). Then (res => {values[I] = res; count++; // This will be a big pity. The MyPromise state will become a big pity if (count === list.length) resolve(values); }, err => {// MyPromise is rejected reject(err); }); }}); } // add static race(list) {returnNew MyPromise((resolve, reject) => {for (let p of list) { Resolve (p). Then (res => {resolve(res); }, err => { reject(err); }); }}); }}Copy the code
Promise A + specification
async/await
The async function, which is the syntactic sugar of a Generator function, implicitly returns a Promise
An async function is implemented by wrapping a Generator and an autoexecutor in a function that returns a promise and can be called directly using the then() method. Resume operation
Async receives the returned value and determines success if it is not an exception or reject. The async function can return values of various data types, false,NaN,undefined… Resolve, but async fails by returning async reject
Contains variables or functions that are directly used and not declared.
- Reject (‘ reject failed ‘) return promise.reject (‘ reject failed ‘)
- Function method execution error (🌰 : Object using push()), etc…
In async, you must return the result, otherwise the async is undefine, reject and Resolved. Arrow functions are recommended
In fact await is a flag to give up the thread. The function after await is executed once (such as await Fn(), not the next line of code) and then jumps out of the whole async function to execute the code behind the JS stack. After the completion of this round of event loop, it will jump back to the async function and wait for the return value of the expression after await****. If the return value is non-promise, it will continue to execute the code after the async function. Otherwise, the returned promise is put into the Promise Queue (promise Job Queue)
The async/await and generator schemes have an important advantage over promises :Promise errors need to be caught by callback functions, and try catches don’t work. While async/await and generator allow try/catch
async function async1() { console.log("async1 start"); // await async2(); Async1 // console.log("async1 end"); async1 // console.log("async1 end"); // The statement immediately following await is put in a new Promise, New Promise(resolve => {console.log("async2") resolve()}).then(res => console.log("async1 end")) } async function async2() { console.log("async2"); } async1(); Console. log("start")// After the macro task has been completed, execute the content just after await async1 end // output result 'async1 start' 'async2' 'start' 'asynC1 end'Copy the code
async function async1() { console.log('async1 start'); Resolve (resolve => {console.log('promise1') resolve(); resolve('promise1') resolve(); Await, await but still no response... }) console.log('async1 success');}) console.log('async1 success');}) console.log('async1 success'); return 'async1 end' } console.log('srcipt start') async1().then(res => console.log(res)) console.log('srcipt end') 'script start' 'async1 start' 'promise1' 'script end' async1 success asynC1 endCopy the code
Features:
- Like promise, it’s non-blocking. But don’t write then and its callback
- Make asynchronous code more similar to synchronous code in form
- Await is an operator used to form an expression that blocks subsequent code. If you wait for a Promise object, you get its resolve value. Otherwise, you get the result of an expression
Async processing error
In async, what happens if the content after await is an exception or error?
async function async1 () { await async2(); console.log('async1'); return 'async1 success' } async function async2 () { return new Promise((resolve, Reject) => {console.log('async2') reject('error')})} async1().then(res => console.log(res)) Terminates the error result and does not proceed. 'async 'Uncaught (in promise) error or: async function async1 () {console.log('async1'); throw new Error('error!!! ') return 'async1 success'} async1(). Then (res => console.log(res)) result: 'async1' Uncaught (in promise) Error: Error!!!Copy the code
If you want to make sure that the error does not affect the subsequent execution of async, you can use a try catch
async function async1 () { try { await Promise.reject('error!!! ')} catch(e) {console.log(e)} // or: // await promise.reject ('error!!! ') // .catch(e => console.log(e)) console.log('async1'); Resolve ('async1 success')} async1().then(res => console.log(res)) console.log('script start') // output 'script start' 'error!!! ' 'async1' 'async1 success'Copy the code
Optimize multiple await
While waiting for an asynchronous operation to complete with async/await, it would be better to fire simultaneously if there is no dependency between the two asynchronous operations, because await must be followed by a Promise instance. You can then combine multiple Promise instances into a single Promise instance using the promise.all () method
Implement async/await
The principle is to split code fragments using generators. Then we use a function that iterates over itself, with each yield wrapped in a promise. The timing of the next step is controlled by the promise
Async /await is the keyword and cannot override its methods, we use functions to emulate
Asynchronous iteration, simulating asynchronous functions
function _asyncToGenerator(fn) { returnfunction() { var self = this, args = arguments; Var gen = fn.apply(self, args); var gener.apply (self, args); Function _next(value) {asyncGeneratorStep(gen, resolve, reject, _next, _throw, 'next', value); } function _throw(err) {asyncGeneratorStep(gen, resolve, reject, _next, _throw, 'throw', err); } // First trigger _next(undefined); }); }; }Copy the code
Perform iteration steps to process the results of the next iteration
function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) {// the iterator completes resolve(value); Resolve (1) a is a promise // const b = Resolve (a) b is a Promise. // If the Promise is finished, then the next function will be called recursively. Until done == true promise.resolve (value). Then (_next, _throw); }}Copy the code
// Test _asyncToGenerator const asyncFunc = _asyncToGenerator(function*() {const e = yieldnewPromise(resolve => { setTimeout(() => { resolve('e'); }, 1000); }); const a = yieldPromise.resolve('a'); const d = yield'd'; const b = yieldPromise.resolve('b'); const c = yieldPromise.resolve('c'); return [a, b, c, d, e]; }); asyncFunc().then(res => { console.log(res); // ['a', 'b', 'c', 'd', 'e'] });Copy the code
Advantages of Async over Promise
- It handles then chains better than Promise
function step1(n) {
console.log(`step1 with ${n}`);
return takeLongTime(n);
}
function step2(n) {
console.log(`step2 with ${n}`);
return takeLongTime(n);
}
function step3(n) {
console.log(`step3 with ${n}`);
return takeLongTime(n);
}
function takeLongTime(n) {
return new Promise(resolve => {
setTimeout(() => resolve(n + 200), n);
});
}
Copy the code
Now use the Promise approach to implement all three steps of processing
function doIt() {
console.time("doIt");
const time1 = 300;
step1(time1)
.then(time2 => step2(time2))
.then(time3 => step3(time3))
.then(result => {
console.log(`result is ${result}`);
});
}
doIt();
// step1 with 300
// step2 with 500
// step3 with 700
// result is 900
Copy the code
If implemented with async/await, it would look like this:
async function doIt() {
console.time("doIt");
const time1 = 300;
const time2 = await step1(time1);
const time3 = await step2(time2);
const result = await step3(time3);
console.log(`result is ${result}`);
}
doIt();
Copy the code
- The median
Each step now requires the result of each previous step.
Function doIt() {console.time("doIt"); function doIt() {console.time("doIt"); const time1 = 300; step1(time1) .then(time2 => { return step2(time1, time2) .then(time3 => [time1, time2, time3]); }) .then(times => { const [time1, time2, time3] = times; return step3(time1, time2, time3); }) .then(result => { console.log(`result is ${result}`); }); } doIt();Copy the code
Async function doIt() {console.time("doIt"); async function doIt() {console.time("doIt"); const time1 = 300; const time2 = await step1(time1); const time3 = await step2(time1, time2); const result = await step3(time1, time2, time3); console.log(`result is ${result}`); } doIt(); // No redundant intermediate values, more elegantly implementedCopy the code
- debugging
It’s easier to debug than Promise, because there’s no code block, so you can’t set breakpoints in a returned arrow function. If you use the debugger step-over in a.then block, the debugger does not go into subsequent.then blocks, because the debugger can only track each step of the synchronized code
Limit the number of concurrent asynchronous operations and complete them as quickly as possible
There is already a function called function loadImg that enters a URL link and returns a Promise that will resolve and reject when the image is downloaded, and guarantee 3 concurrent requests per download. So we can request the first three urls (subscripts 0,1,2) and use promise.race () to request both urls at the same time, with one of the three completed first (for example, images with subscripts 1). We simply replace the completed item (item 1) in the current array with the one that has not yet been requested (subscript 3 in urls) until the urls have been traversed, and then load the last three uncompleted requests (that is, promises with no state change) with promise.all ()
var urls = [ "https://hexo-blog-1256114407.cos.ap-shenzhen-fsi.myqcloud.com/AboutMe-painting1.png", "https://hexo-blog-1256114407.cos.ap-shenzhen-fsi.myqcloud.com/AboutMe-painting2.png", "https://hexo-blog-1256114407.cos.ap-shenzhen-fsi.myqcloud.com/AboutMe-painting3.png", "https://hexo-blog-1256114407.cos.ap-shenzhen-fsi.myqcloud.com/AboutMe-painting4.png", "https://hexo-blog-1256114407.cos.ap-shenzhen-fsi.myqcloud.com/AboutMe-painting5.png", "https://hexo-blog-1256114407.cos.ap-shenzhen-fsi.myqcloud.com/bpmn6.png", "https://hexo-blog-1256114407.cos.ap-shenzhen-fsi.myqcloud.com/bpmn7.png", "https://hexo-blog-1256114407.cos.ap-shenzhen-fsi.myqcloud.com/bpmn8.png", ]; function loadImg(url) { return new Promise((resolve, reject) => { const img = new Image(); Img. onload = function () {console.log(" an image is loaded "); resolve(img); }; img.onerror = function () { reject(new Error('Could not load image at' + url)); }; img.src = url; })}; Function limitLoad(urls, handler, limit) {let sequence = [].concat(urls); Let promises = sequence.splice(0, limit).map((url, Return handler(url). Then (() => {return handler(url). }); }); // Note that the whole variable procedure is returned, and the result is a Promise, Return sequence. reduce((pCollect, url) => {return pCollect. Then (() => {return promise.race (promises); // fastestIndex => {// fastestIndex => {// fastestIndex => {// fastestIndex => {// => { return fastestIndex; // continue to return the subscript for the next variable}); }) .catch(err => { console.error(err); }); }, promise.resolve ()) // initialize the pass.then (() => {return promise.all (promises); }); } limitLoad(urls, loadImg, 3). Then (res => {console.log(" all images are loaded "); console.log(res); }) .catch(err => { console.error(err); });Copy the code
The application of Generator in flow control
How does Generator address the lack of orderality in traditional callbacks?
function getCallSettings() { utils.ajax({ url: '/dialer/dialerSetting', method: "GET", success: (res) => { it.next(res.dialerSetting); }, error: (err) => {it. Throw (err); // Throw an error}}); } function *dealData() { try{ let settingInfo = yield getCallSettings(); / / do something... } catch(err) { console.log(err); }} let it = dealData(); it.next(); // Start the generatorCopy the code
Yield is used to suspend blocking code in an asynchronous process. It blocks only code inside the generator, and nothing outside the generator is affected. let settingInfo = yield getCallSettings(); In yield, asynchronous processes are completely removed and code that looks sequentially synchronized is a huge improvement
Arrow function
- This cannot be changed by call, apply
- Instead of binding arguments objects, use rest arguments… Solve the problem of getting extra arguments to a function
- Cannot be called by the new keyword
- JS functions have two internal methods: Call and Construct.
- When a function is called from new, the Construct method is executed to create an instance object, and then the function body is executed, binding this to the instance. When called directly, the Call method is executed to execute the function body directly
- The arrow function has no Construct method and cannot be used as a constructor. A call to new will result in an error
var Foo = () => {};
var foo = new Foo(); // TypeError: Foo is not a constructor
Copy the code
- There is no prototype, so it cannot be used as a constructor, so the arrow function itself does not have this
- Since you can’t call the arrow function with new, there’s no need to build a prototype, so the arrow function doesn’t have the prototype property
var Foo = () => {};
console.log(Foo.prototype); // undefined
Copy the code
- Has a __proto__ attribute, so the arrow function itself has a prototype chain, and it also has its own constructor
- But the link between the prototype and the arrow function stops because it has no prototype property of its own to point to by its instance’s __proto__ property, so the arrow function cannot be used as a constructor
- This refers to this, which inherits from the first normal function in the outer layer at definition, regardless of where it is used
- The this of the inherited normal function changes, and the this of the arrow function changes with it
Let a, barObj = {MSG: 'bar this to '}; FooObj = {MSG: 'foo this points to '}; bar.call(barObj); // Point bar's this to barObj foo.call(fooObj); // Set foo's this to fooObj function foo() {a(); } function bar() {a = () => {console.log(this, 'this' refers to the first normal function defined at the time '); / /}; // Define this in bar as inheriting from the bar function that this refers to}Copy the code
Var,let const, variable promotion, temporary dead zone
How variable promotion works: JS, like any other language, goes through compilation and execution phases. It is during this brief compilation phase that the JS engine collects all variable declarations and validates them in advance. As for the rest of the statements, they will not take effect until the execution phase, when a specific sentence is executed. This is the mechanism behind variable promotion
- Var: Declarations and variable declarations inside functions are promoted to the top of the scope, but values are not
- Let: variable will be bound to a piece of scope, it showed the similar characteristics – out of the scope and function block scope, we won’t be able to access the inside of the variables, and the var is not perception scope, namely with the variables of the var statement in the code block, the block of code can access to the outside, let not repeat statement, to the role assignment, : Var ->let; var->let; var->let
- Const: Const is declared as a constant and must be initialized and cannot be reassigned, otherwise an error will be reported. The constant declared by const is locked in the first place. Do not try to point to a new memory space
Person ={name:' WSN '} const person={name:' WSN '} const person={name:' WSN '} const person={name:' WSN '} const person={name:' WSN '} const person={name:' WSN '} {name:'hh'} person = {name:'hh'} person = {name:'hh'} person = {name:'hh'} person = {name:'hh'} person = {name:'hh'Copy the code
This is because the object or array belongs to the reference data class. Changing the reference of the object or array changes the memory address of the referenced object. Adding or deleting data in the original object or array does not change the memory address of the object where the member resides, so no error will be reported
Let and const 1: const me = ‘xiuyan’ me = ‘Bear’// Error when resetting values There is no variable promotion, it must be declared before it can be called otherwise an error will be reported, this is a deferred dead zone (to reduce runtime errors, prevent use before declaration)
Read for reference:
Juejin. Cn/post / 684490… Juejin. Cn/post / 684490… Juejin. Cn/post / 684490…