A Promise from scratch
A Promise from scratch
1. Prepare knowledge
1.1 Instance objects and function objects
- Instance objects: Objects generated by the new function are called instance objects, or objects for short
- Function objects: When functions are used as objects, they are called function objects
Function Fn() {// Fn can only be called a function} const Fn = new Fn() // Fn can only be called a constructor // Fn is called console.log(fn.prototype)// Bind ({}) // $.get('/test') // $.get('/test') // $Copy the code
Function to the left, object to the left (function object, instance object)
1.2 Two types of callback functions
1. What is a callback function
- You define
- You don’t have the
- Finally he did
2. Common callback functions and asynchronous operations
- Dom event callback function
- Timer callback function,
- Ajax callback function
- Lifecycle callback function
- Database operations
- Fs file operation
require('fs').readFile('./index.html', (err,data)=>{})\
3. Synchronize the callback
Execute immediately, complete, and not put into the callback queue
Array traversal of the associated callback/Promise executor function
const arr = [1, 3, 5]; Arr. ForEach (item => {// loop through callback, synchronize callback, will not be queued, first call console.log(item); }) console.log(' after forEach() ')Copy the code
4. Asynchronous callback
It will not be executed immediately and will be placed in the callback queue for future execution
Timer callback/Ajax callback/Promise successful or failed callback
Log ('timeout callback()')}, 0) console.log('setTimeout() ')Copy the code
New Promise((resolve, reject) => {resolve(1)}). Then (value => {console.log('value', value)}, reason => {console.log('reason', reason)} ) console.log('----') // ---- // value 1Copy the code
The js engine executes the code in the callback queue after completing the initial synchronization
1.3 Error handling in JS
1. Wrong type
Error: The parent type of all errors
2. ReferenceError: The referenced variable does not exist
console.log(a) // ReferenceError:a is not defined
TypeError: Indicates that the data type is incorrect
let b
console.log(b.xxx)
// TypeError:Cannot read property 'xxx' of undefined
let c = {}
c.xxx()
// TypeError:c.xxx is not a function
Copy the code
4. RangeError: The data value is not in the allowed range
function fn() {
fn()
}
fn()
// RangeError:Maximum call stack size exceeded
Copy the code
5. SyntaxError: SyntaxError
const c = """"
// SyntaxError:Unexpected string
Copy the code
2. Error handling (catch and throw)
Throw error: Throw error
Function something() {if (date.now ()%2===1) {console.log(' the current time is odd, the task can be performed ')} else {// If the time is even, throw an exception, Throw new Error(' Current time is even, task cannot be performed ')}}Copy the code
Catch error: try… catch
Try {something()} catch (error) {alert(error. Message)}Copy the code
3. Error object
- Massage attribute: error related information
- Stack property: Function call stack record information
try { let d console.log(d.xxx) } catch (error) { console.log(error.message) console.log(error.stack) } Console. log(' error after ') // Cannot read property 'XXX' of undefined // TypeError:Cannot read property 'XXX' of undefined // After the errorCopy the code
Because the error is caught and handled, the following code can run, printing ‘after the error’
2. Understanding and use of Promise
2.1 What is Promise
1. Understand the Promise
-
Abstract expression:
- Promise is a new technology (ES6 specification)
- Promise is a new solution for asynchronous programming in JS
Note: The old scheme used the callback function only
-
Specific expressions:
- Syntactically, a Promise is a constructor (all, Reject, resolve, prototype then, catch, etc.)
- Functionally: The Promise object encapsulates an asynchronous operation and can retrieve its success/failure value
-
Ruan Yifeng explains:
- A Promise is simply a container that holds the result of an event (usually an asynchronous operation) that will end in the future.
- Syntactically, a Promise is an object from which to get messages for asynchronous operations
- Promise provides a uniform API, and all kinds of asynchronous operations can be handled in the same way
2. Promise status changes
PromiseState, a property of the instance object promise
- Pending resolved/fullfilled
- Pending a rejected
Pay attention to
- The status of an object is not affected
- There are only two, and a promise object can only change once
- Once the state changes, it never changes again, and you can get this result at any time
- Success or failure, there will be a result data. The result data for success is usually called value, and the result data for failure is usually called Reason.
3. Value of the Promise object
PromiseResult, which holds the success/failure value of the object (value/reason).
- Resolve /reject you can change the value
4. Basic process of Promise
5. Basic use of Promises
The Promise constructor takes a function (the executor function) as an argument, resolve and reject. They are two functions that are provided by the JavaScript engine and do not need to be deployed themselves.
The resolve function changes the state of the Promise object from “unfinished” to “successful” (that is, from pending to Resolved), calls it when the asynchronous operation succeeds, and passes the result of the asynchronous operation as value.
The Reject function changes the state of the Promise object from “unfinished” to “failed” (i.e., from Pending to Rejected). The reject function is called when the asynchronous operation fails and passes the errors reported by the asynchronous operation as error/ Reason.
After the Promise instance is generated, you can use the THEN method to specify the resolved and Rejected state callback functions, respectively.
promise.then(function(value) {
// success
}, function(reason) {
// failure
});
Copy the code
The then method can take two callback functions as arguments. The first callback, onResolved(), is called when the Promise object’s state changes to Resolved. The second callback, onRejected(), is called when the Promise object’s state changes to Rejected. These two functions are optional and do not have to be provided. They all accept the value passed out from the Promise object as an argument
.then() and executor are executed synchronously, and callbacks in.then() are executed asynchronously
1) Use 1: basic coding process
<script> // 1) Create a promise object (pending state), specify the executor function const p = new promise ((resolve, Reject) => {// 2) start async task setTimeout(() => {const time = date.now () // 3) do different processing according to the result // 3.1) Resolve () if (time % 2 === 1) {resolve(' successful value '+ time)} else {// 3.2) Reject () {reject() {reject() {reject(' reject '+ time)}} Error: error: error: error: error: error: error: error: error: error: error: error: error: error: error: error: error: error Get successful vlaue console.log(' successful value: ', value)}, reason => {// Failed callback function onRejected, get failed reason console.log(' failed reason: ', reason)}) </script>Copy the code
2) Use 2: Use promise to encapsulate timer-based asynchrony
<script> function doDelay(time) { // 1. Return new promise ((resolve, reject) => {// 2. Log (' Start asynchronous task ') setTimeout(() => {console.log(' Delay task start execution... ') const time = date.now () // If (time % 2 === 1) {// Succeeded // 3. 1. If successful, call resolve() and pass the successful value resolve(' successful data '+ time)} else {// failed // 3.2. If this fails, call reject() and pass in the failed reason reject(' failed data '+ time)}}, Time)})} const promise = doDelay(2000) promise.then(value => {console.log(' successful value: ', value)}, reason => {console.log(' failed reason: ', reason)},) </script>Copy the code
3) Use 3: Use promises to encapsulate ajax asynchronous requests
<script> /* Reusable ajax request function: xhr + promise */ function promiseAjax(url) { return new Promise((resolve, reject) => { const xhr = new XMLHttpRequest() xhr.onreadystatechange = () => { if (xhr.readyState ! == 4) return const {status, response} = XHR Resolve (value) if (status >= 200 && status < 300) {resolve(json.parse (response))} else {// Request failed, Reject (Reason) reject(new Error(' Request failed: status: ' + status)) } } xhr.open("GET", url) xhr.send() }) } promiseAjax('https://api.apiopen.top2/getJoke? Page =1&count=2&type=video'). Then (data => {console.log(' display successful data ', data)}, error => {alert(error. Message)}) </script>Copy the code
2.2 Why use Promise?
1. More flexibility in the way callback functions are specified
- Old: Must be specified before starting asynchronous tasks
- Promise: Start asynchronous task => return promie object => Bind callback function to Promise object (can even specify/multiple after asynchronous task ends)
2. Support chain call, can solve the problem of callback hell
1. What is callback hell?
The callback function is called nested, and the result of the asynchronous execution of the external callback function is the condition for the nested callback to execute
2. Callback to hell’s faults?
Not easy to read and not easy to handle exceptions
3. Solution?
Promise chain call
4. Ultimate solution?
async/await
<script> /* 1. The way to specify callback functions is more flexible: old: You must specify a promise before starting an asynchronous task: Start the asynchronous task => return the Promie object => Bind the callback function to the Promise object (you can even specify it after the asynchronous task ends) 2. Support for chained calls to solve the problem of callback hell what is callback hell? Callback function nested calls, external callback function asynchronously executed as a result of nested callback function number executed conditional callback hell disadvantage? Not easy to read/not easy exception handling solution? Promise chain call ultimate solution? Async /await */ / function successCallback(result) {console.log(" sound file created successfully: "+ result); } function failureCallback(error) {console.log(" failed to create sound file: "+ error); } /* createAudioFileAsync(audioSettings, successCallback, failureCallback) /* 1.2. Use Promise */ const Promise = createAudioFileAsync(audioSettings); // 2 setTimeout(() => { promise.then(successCallback, failureCallback); }, 3000); Function (result) {doSomethingElse(result, function (newResult) {doThirdThing(newResult, function (newResult)) {doThirdThing(newResult, function (newResult)); function (finalResult) { console.log('Got the final result: '+ finalResult)}, failureCallback)}, failureCallback)}, failureCallback) /* 2.2. Use promise's chained calls to solve callback hell */ doSomething().then(function (result) {return doSomethingElse(result)}).then(function) (newResult) { return doThirdThing(newResult) }) .then(function (finalResult) { console.log('Got the final result: '+ finalResult)}). Catch (failureCallback) /* 2.3. Async /await: */ async function Request () {try {const result = await doSomething() const newResult = await doSomethingElse(result) const finalResult = await doThirdThing(newResult) console.log('Got the final result: ' + finalResult) } catch (error) { failureCallback(error) } } </script>Copy the code
3. Code examples
Promise implements timer – lottery
<! Doctype HTML > < HTML lang="en"> <head> <meta charset="UTF-8"> <title> Href = "https://cdn.bootcss.com/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel = "stylesheet" > < / head > < body > < div Class ="container"> <h2 class="page-header">Promise </ H2 > <button class=" BTN bTN-primary "id=" BTN "> Function rand(m, n) {return math.ceil (math.random () * (n-m + 1)) + m-1; } /** Click the button, 1s after the display whether winning (30% probability of winning) */ // get the element object const BTN = document.querySelector('# BTN '); // Bind the click event btn.addEventListener('click', Function () {// timer // setTimeout(() => {// //30% 1-100 // // get a random number from 1-100 // let n = rand(1, 100); / / / / / / the if (n = 30) {/ / alert (' congratulations, the prize is 100000 RMB Rolls-Royce coupons'); //}else{// alert(' keep up the good work '); //} //}, 1000); Const p = new Promise((resolve, resolve, reject)) Reject) => {setTimeout(() => {//30% 1-100 1 2 30 // get a random number from 1-100 let n = rand(1, 100); If (n <= 30) {resolve(n); // Set the state of the Promise object to "success"} else {reject(n); // Set the state of the Promise object to "fail"}}, 1000); }); console.log(p); // then call // value // reason // P.teng ((value) => {// The object status is successful alert(' congratulations, the prize is 100,000 RMB rolls Royce coupon, your winning number is' + value); }, (reason) => {// The object status is failed callback alert(' Keep up the good work, your number is' + reason); }); }); </script> </body> </html>Copy the code
Promise implements a FS module that reads the contents of the file
Promise to realize
const fs = require('fs');
// callback function form
// fs.readFile('./resource/content.txt', (err, data) => {
// // Throws an error if there is an error
// if (err) throw err;
// // Displays the file content
// console.log(data.toString());
// });
/ / Promise
let p = new Promise((resolve, reject) = > {
fs.readFile('./resource/content.txt'.(err, data) = > {
// If something goes wrong
if (err) reject(err);
// If successful
resolve(data);
});
});
/ / call then
p.then(value= > {
console.log(value.toString());
}, reason= > {
console.log(reason);
});
Copy the code
Encapsulate it, and you can directly follow.then
/** * Encapsulates a function called mineReadFile to read the contents of the file. */ function mineReadFile(path){return new promise ((resolve, Reject) =>{// readFile require('fs'). ReadFile (path, (err, data) =>{// judge if(err) reject(err); / / success resolve (data); }); }); } mineReadFile('./resource/content.txt').then(value=>{// Output file content console.log(value.tostring ()); }, reason=>{ console.log(reason); });Copy the code
Util. Promisify method
Const util = require('util'); Const fs = require('fs'); // Return a new function let mineReadFile = util.promisify(fs.readfile); mineReadFile('./resource/content.txt').then(value => { console.log(value.toString()); });Copy the code
Promise to implement AJAX
<! DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, <title> <link crossorigin='anonymous' Href = "https://cdn.bootcss.com/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel = "stylesheet" > < / head > < body > < div Class ="container"> <h2 class="page-header">Promise encapsulates AJAX operations </h2> <button class=" BTN bTN-primary "ID =" BTN "> Click send AJAX < / button > < / div > < script > / / / / interface address https://api.apiopen.top/getJoke access element object const BTN = document.querySelector('#btn'); Btn.addeventlistener ('click', function () {// create Promise const p = new Promise((resolve, reject) => {//1. Create object const XHR = new XMLHttpRequest(); / / 2. Initialization XHR. Open (' GET 'and' https://api.apiopen.top/getJoke '); / / 3. XHR. The send (); Xhr.onreadystatechange = function () {if (xhr.readyState === 4) {// Determine the response status code 2xx if (xhr.status >= 200&& Xhr.status < 300) {// Console outputs the response body // unwrapped console.log(xhr.response); resolve(xhr.response); } else {// Console outputs response status code // unwrapped console.log(xhr.status); reject(xhr.status); }}}}); // Call then method p.teng (value => {console.log(value); }, reason => { console.warn(reason); }); }); </script> </body> </html>Copy the code
Use promises to encapsulate ajax asynchronous requests
<! DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, Initial-scale =1.0"> <title>Promise wraps AJAX operations </title> </head> <body> <script> /** * wraps a function sendAJAX to send GET AJAX request * parameter URL */ function sendAJAX(url) {return new Promise((resolve, resolve) reject) => { const xhr = new XMLHttpRequest(); xhr.responseType = 'json'; xhr.open("GET", url); xhr.send(); Xhr.onreadystatechange = function () {if (xhr.readyState === 4) {if (xhr.status >= 200 && xhr.status < Resolve (xhr.response); } else { reject(xhr.status); }}}}); } sendAJAX('https://api.apiopen.top/getJoke') .then(value => { console.log(value); }, reason => { console.warn(reason); }); </script> </body> </html>Copy the code