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

  1. You define
  2. You don’t have the
  3. 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:

    1. Promise is a new technology (ES6 specification)
    2. Promise is a new solution for asynchronous programming in JS

    Note: The old scheme used the callback function only

  • Specific expressions:

    1. Syntactically, a Promise is a constructor (all, Reject, resolve, prototype then, catch, etc.)
    2. Functionally: The Promise object encapsulates an asynchronous operation and can retrieve its success/failure value
  • Ruan Yifeng explains:

    1. A Promise is simply a container that holds the result of an event (usually an asynchronous operation) that will end in the future.
    2. Syntactically, a Promise is an object from which to get messages for asynchronous operations
    3. 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

  1. Pending resolved/fullfilled
  2. 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

  1. Old: Must be specified before starting asynchronous tasks
  2. 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