18_Promise
使用express模拟后端
myapi工程:index.js
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
const express = require('express') const app = express() const bodyParser = require('body-parser') // 处理静态资源 app.use(express.static('public')) // 处理参数 app.use(bodyParser.json()); app.use(bodyParser.urlencoded({ extended: false })); // 设置允许跨域访问该服务 app.all('*', function (req, res, next) { res.header("Access-Control-Allow-Origin", "*"); res.header('Access-Control-Allow-Methods', 'PUT, GET, POST, DELETE, OPTIONS'); res.header("Access-Control-Allow-Headers", "X-Requested-With"); res.header('Access-Control-Allow-Headers', 'Content-Type'); res.header('Access-Control-Allow-Headers', 'mytoken'); next(); }); app.get('/async1', (req, res) => { res.send('hello1') }) app.get('/async2', (req, res) => { if(req.query.info == 'hello') { res.send('world') }else{ res.send('error') } }) app.get('/adata', (req, res) => { res.send('Hello axios!') }) app.get('/axios', (req, res) => { res.send('axios get 传递参数' + req.query.id) }) app.get('/axios/:id', (req, res) => { res.send('axios get (Restful) 传递参数' + req.params.id) }) app.delete('/axios', (req, res) => { res.send('axios get 传递参数' + req.query.id) }) app.post('/axios', (req, res) => { res.send('axios post 传递参数' + req.body.uname + '---' + req.body.pwd) }) app.put('/axios/:id', (req, res) => { res.send('axios put 传递参数' + req.params.id + '---' + req.body.uname + '---' + req.body.pwd) }) app.get('/axios-json', (req, res) => { res.json({ uname: 'lisi', age: 12 }); }) app.get('/fdata', (req, res) => { res.send('Hello Fetch!') }) app.get('/books', (req, res) => { res.send('传统的URL传递参数!' + req.query.id) }) app.get('/books/:id', (req, res) => { res.send('Restful形式的URL传递参数!' + req.params.id) }) app.delete('/books/:id', (req, res) => { res.send('DELETE请求传递参数!' + req.params.id) }) app.post('/books', (req, res) => { res.send('POST请求传递参数!' + req.body.uname + '---' + req.body.pwd) }) app.put('/books/:id', (req, res) => { res.send('PUT请求传递参数!' + req.params.id + '---' + req.body.uname + '---' + req.body.pwd) }) app.get('/json', (req, res) => { res.json({ uname: 'lisi', age: 13, gender: 'male' }); }) app.get('/a1', (req, res) => { setTimeout(function(){ res.send('Hello TOM!') },1000); }) app.get('/a2', (req, res) => { setTimeout(function(){ res.send('Hello JERRY!') },2000); }) app.get('/a3', (req, res) => { setTimeout(function(){ res.send('Hello SPIKE!') },3000); }) // 路由 app.get('/data', (req, res) => { res.send('Hello World!') }) app.get('/data1', (req, res) => { setTimeout(function(){ res.send('Hello TOM!') },1000); }) app.get('/data2', (req, res) => { res.send('Hello JERRY!') }) // 启动监听 app.listen(3000, () => { console.log('running...') })
安装nodemon
npm i -g nodemon
运行express工程:
nodemon index.js
-
原生ajax
-
基于jQuery的ajax
-
fetch
-
axios
异步
-
JavaScript的执行环境是「单线程」
-
所谓单线程,是指JS引擎中负责解释和执行JavaScript代码的线程只有一个,也就是一次只能完成一项任务,这个任务执行完后才能执行下一个,它会「阻塞」其他任务。这个任务可称为主线程
-
异步模式可以一起执行多个任务
-
JS中常见的异步调用
-
定时任务
-
ajax
-
事件函数
-
异步案例:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> </head> <body> <div>前后端交互</div> <script type="text/javascript" src="js/jquery.js"></script> <script type="text/javascript"> /* 前后端交互-异步编程与Promise概述 */ var ret = '---'; $.ajax({ url: 'http://localhost:3000/data', success: function (data) { ret = data; console.log(ret) } }); console.log(ret) // ---------------------------- $.ajax({ url: 'http://localhost:3000/data', success: function (data) { console.log(data) } }); $.ajax({ url: 'http://localhost:3000/data1', success: function (data) { console.log(data) } }); $.ajax({ url: 'http://localhost:3000/data2', success: function (data) { console.log(data) } }); // ----------------------------------- $.ajax({ url: 'http://localhost:3000/data', success: function (data) { console.log(data) $.ajax({ url: 'http://localhost:3000/data1', success: function (data) { console.log(data) $.ajax({ url: 'http://localhost:3000/data2', success: function (data) { console.log(data) } }); } }); } }); </script> </body> </html>
promise
-
主要解决异步深层嵌套的问题
-
promise 提供了简洁的API 使得异步操作更加容易
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> </head> <body> <script type="text/javascript"> /* 1. Promise基本使用 我们使用new来构建一个Promise Promise的构造函数接收一个参数,是函数。并且传入两个参数:resolve,reject,分别表示异步操作执行成功后的回调函数和异步操作执行失败后的回调函数 */ // console.log(typeof Promise) // console.dir(Promise); var p = new Promise(function (resolve, reject) { //2.这里用于实现异步任务:setTimeout setTimeout(function () { var flag = false; if (flag) { //3.正常情况 resolve('hello'); } else { //4.异常情况 reject('出错了'); } }, 100); }); //5、Promise实例生成以后,可以用then方法指定resolved状态和reject状态的回调函数 // 在then方法中,你也可以直接return数据而不是Promise对象,在后面的then中就可以接收到数据了 p.then(function (data) { console.log(data) }, function (info) { console.log(info) }); </script> </body> </html>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> </head> <body> <script type="text/javascript"> /* 基于Promise发送Ajax请求 */ function queryData(url) { // 1.1 创建一个Promise实例 var p = new Promise(function (resolve, reject) { var xhr = new XMLHttpRequest(); xhr.onreadystatechange = function () { if (xhr.readyState != 4) return; if (xhr.readyState == 4 && xhr.status == 200) { // 1.2 处理正常的情况 resolve(xhr.responseText); } else { // 1.3 处理异常情况 reject('服务器错误'); } }; xhr.open('get', url); xhr.send(null); }); return p; } // 注意:这里需要开启一个服务 // 在then方法中,你也可以直接return数据而不是Promise对象,在后面的then中就可以接收到数据了 queryData('http://localhost:3000/data') .then(function(data){ console.log(data); },function(info){ console.log(info) }); // ============================ // 发送多个ajax请求并且保证顺序 queryData('http://localhost:3000/data') .then(function (data) { console.log(data) // 1.4 想要继续链式编程下去 需要 return return queryData('http://localhost:3000/data1'); }) .then(function (data) { console.log(data); return queryData('http://localhost:3000/data2'); }) .then(function (data) { console.log(data) }).then(data => console.log(data)); </script> </body> </html>
then参数中的函数的返回值:
1、为promise对象时可以继续调用then链式操作
2、为普通返回值对象下次调用then时参数值为该对象
Promise实例方法:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> </head> <body> <script type="text/javascript"> /* Promise常用API-实例方法 */ // console.dir(Promise); function foo() { return new Promise(function(resolve, reject){ setTimeout(function(){ // resolve(123); reject('error'); }, 100); }) } // foo() // .then(function(data){ // console.log(data) // }) // .catch(function(data){ // console.log(data) // }) // .finally(function(){ // console.log('finished') // }); // -------------------------- // 两种写法是等效的 foo() .then(function(data){ console.log(data) },function(data){ console.log(data) }) .finally(function(){ console.log('finished') }); </script> </body> </html>
静态方法
.all()
-
Promise.all
方法接受一个数组作参数,数组中的对象(p1、p2、p3)均为promise实例(如果不是一个promise,该项会被用Promise.resolve
转换为一个promise)。它的状态由这三个promise实例决定
.race()
-
Promise.race
方法同样接受一个数组作参数。当p1, p2, p3中有一个实例的状态发生改变(变为fulfilled
或rejected
),p的状态就跟着改变。并把第一个改变状态的promise的返回值,传给p的回调函数
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> </head> <body> <script type="text/javascript"> /* Promise常用API-对象方法 */ // console.dir(Promise) function queryData(url) { return new Promise(function (resolve, reject) { var xhr = new XMLHttpRequest(); xhr.onreadystatechange = function () { if (xhr.readyState != 4) return; if (xhr.readyState == 4 && xhr.status == 200) { // 处理正常的情况 resolve(xhr.responseText); } else { // 处理异常情况 reject('服务器错误'); } }; xhr.open('get', url); xhr.send(null); }); } var p1 = queryData('http://localhost:3000/a1'); var p2 = queryData('http://localhost:3000/a2'); var p3 = queryData('http://localhost:3000/a3'); // all中的参数[p1,p2,p3]和返回的结果一 一对应["HELLO TOM", "HELLO JERRY", "HELLO SPIKE"] Promise.all([p1, p2, p3]).then(function (result) { console.log(result) // ["HELLO TOM", "HELLO JERRY", "HELLO SPIKE"] }) // 由于p1执行较快,Promise的then()将获得结果'P1'。p2,p3仍在继续执行,但执行结果将被丢弃。 Promise.race([p1, p2, p3]).then(function (result) { console.log(result) // "HELLO TOM" }) </script> </body> </html>