Promise学习——解决回调地狱问题
生活随笔
收集整理的這篇文章主要介紹了
Promise学习——解决回调地狱问题
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
Promise
promise 容器概念:
callback hell(回調地獄):
文件的讀取無法判斷執行順序(文件的執行順序是依據文件的大小來決定的)(異步api無法保證文件的執行順序)
var fs = require('fs');fs.readFile('./data/a.text','utf8',function(err,data){if(err){// 1 讀取失敗直接打印輸出讀取失敗return console.log('讀取失敗');// 2 拋出異常// 阻止程序的執行// 把錯誤信息打印到控制臺throw err;}console.log(data); });fs.readFile('./data/b.text','utf8',function(err,data){if(err){// 1 讀取失敗直接打印輸出讀取失敗return console.log('讀取失敗');// 2 拋出異常// 阻止程序的執行// 把錯誤信息打印到控制臺throw err;}console.log(data); });通過回調嵌套的方式來保證順序:
var fs = require('fs');fs.readFile('./data/a.text','utf8',function(err,data){if(err){// 1 讀取失敗直接打印輸出讀取失敗return console.log('讀取失敗');// 2 拋出異常// 阻止程序的執行// 把錯誤信息打印到控制臺throw err;}console.log(data);fs.readFile('./data/b.text','utf8',function(err,data){if(err){// 1 讀取失敗直接打印輸出讀取失敗return console.log('讀取失敗');// 2 拋出異常// 阻止程序的執行// 把錯誤信息打印到控制臺throw err;}console.log(data);fs.readFile('./data/a.text','utf8',function(err,data){if(err){// 1 讀取失敗直接打印輸出讀取失敗return console.log('讀取失敗');// 2 拋出異常// 阻止程序的執行// 把錯誤信息打印到控制臺throw err;}console.log(data);});}); });為了解決以上編碼方式帶來的問題(回調地獄嵌套),所以在EcmaScript6新增了一個API:Promise。
- Promise:承諾,保證
- Promise本身不是異步的,但往往都是內部封裝一個異步任務
基本語法:
var fs = require('fs') // 在EcmaScript 6 中新增了一個API Promise // Promise 是一個構造函數// 創建 Promise 容器 // 1.給別人一個承諾 I promise you // Promise 容器一旦創建,就開始執行里面的代碼 var p1 = new Promise(function(resolve, reject) {fs.readFile('./data/a.txt', 'utf-8', function(err, data) {if (err) {// 失敗了,承諾容器中的任務失敗了// console.log(err)// 把容器的Pending狀態變為Rejected// 調用的reject方法實際上就是then方法傳遞的第二個參數函數functionreject(err)} else {// 承諾容器中的任務成功了// console.log(data)// 把容器的Pending狀態變為成功// 也就是說這里調用的resolve方法實際上就是then方法傳遞的第一個functionresolve(data)}}) })// p1 就是那個承諾 // 當 p1 成功了,然后(then)做指定的操作 // then 方法接收的function就是容器中的resolve函數 p1.then(function(data) {console.log(data) }, function(err) {console.log('讀取文件失敗', err) })鏈式循環:
封裝Promise的readFile:
var fs = require('fs')function pReadFile(filePath) {return new Promise(function(resolve, reject) {fs.readFile(filePath, 'utf-8', function(err, data) {if (err) {reject(err)} else {resolve(data)}})}) }pReadFile('./data/a.txt').then(function(data) {console.log(data)return pReadFile('./data/b.txt')}).then(function(data) {console.log(data)return pReadFile('./data/c.txt')}).then(function(data) {console.log(data)}) var fs = require('fs') // 在EcmaScript 6 中新增了一個API Promise // Promise 是一個構造函數// 創建 Promise 容器 // 1.給別人一個承諾 I promise you // Promise 容器一旦創建,就開始執行里面的代碼 var p1 = new Promise(function(resolve, reject) {fs.readFile('./data/a.txt', 'utf-8', function(err, data) {if (err) {// 失敗了,承諾容器中的任務失敗了// console.log(err)// 把容器的Pending狀態變為Rejected// 調用的reject方法實際上就是then方法傳遞的第二個參數函數functionreject(err)} else {// 承諾容器中的任務成功了// console.log(data)// 把容器的Pending狀態變為成功// 也就是說這里調用的resolve方法實際上就是then方法傳遞的第一個functionresolve(data)}}) })var p2 = new Promise(function(resolve, reject) {fs.readFile('./data/b.txt', 'utf-8', function(err, data) {if (err) {reject(err)} else {resolve(data)}}) })var p3 = new Promise(function(resolve, reject) {fs.readFile('./data/c.txt', 'utf-8', function(err, data) {if (err) {reject(err)} else {resolve(data)}}) })// p1 就是那個承諾 // 當 p1 成功了,然后(then)做指定的操作 // then 方法接收的function就是容器中的resolve函數 p1.then(function(data) {console.log(data)// 當 p1讀取成功的時候// 當前函數中 return 的結果就可以在后面的 then中function接收到// 當return 一個 promise 對象的時候,后續的then中的方法的第一個參數會作為p2 的resolvereturn p2 }, function(err) {console.log('讀取文件失敗', err) }).then(function(data) {console.log(data)return p3 }).then(function(data) {console.log(data) })需求:分別向兩個接口:users和jobs發送請求,獲取響應數據,將數據通過art-template 模板渲染到html頁面上
第一種:使用自己封裝的callback方式
data.json:
{"users": [{"id": 1,"username": "admin","age": 22,"job": 4},{"id": 2,"username": "admin2","age": 18,"job": 1},{"id": 3,"username": "admin3","age": 18,"job": 1}],"jobs": [{"id": 1,"name": "學生"},{"id": 2,"name": "老師"},{"id": 3,"name": "司機"},{"id": 4,"name": "演員"},{"id": 5,"name": "畫家"},{"id": 6,"name": "電競人"}] }這里使用json-server來開啟一個服務:
首先,安裝 json-server: npm install -g json-server
然后通過命令:json-server --watch data.json啟動服務:
由于用到了模板引擎來將數據渲染到頁面上,所以需要再安裝一個art-template包:
npm i art-template
第二種:使用jquery的promise方式
<!DOCTYPE html> <html><head><meta charset="utf-8"><title></title></head><body><form action="#" id="user_form"></form><script type="text/text/template" id="tpl"><label for="">用戶名</label><input type="text" value="{{ user.username }}"><label for="">年齡</label><input type="text" value="{{ user.age }}"><label for="">職業</label><select name="" id="">{{ each jobs }}{{ if user.job === $value.id }}<option value="{{ $value.id }}" selected="selected">{{ $value.name }}</option>{{ else }}<option value="{{ $value.id }}">{{ $value.name }}</option>{{ /if }} {{ /each }}</select> </script><script src="node_modules/jquery/dist/jquery.js"></script><script src="node_modules/art-template/lib/template-web.js"></script><script>// 用戶表// 其中一個接口獲取用戶數據// 職業:1// 職業信息表// 其中一個接口獲取所有的職業信息/* get('http://127.0.0.1:3000/users/1', function(userData) {// data = JSON.parse(data)get('http://127.0.0.1:3000/jobs', function(jobsData) {// console.log(userData, jobsData)var htmlStr = template('tpl', {user: JSON.parse(userData),jobs: JSON.parse(jobsData)})console.log(htmlStr)document.querySelector('#user_form').innerHTML = htmlStr})}) */var data = {}$.get('http://127.0.0.1:3000/users/1').then(function(userData) {console.log(userData)data.user = userDatareturn $.get('http://127.0.0.1:3000/jobs')}).then(function(jobsData) {console.log(jobsData)data.jobs = jobsDataconsole.log(data)var htmlStr = template('tpl', data)console.log(htmlStr)document.querySelector('#user_form').innerHTML = htmlStr})function get(url, callback) {var oReq = new XMLHttpRequest()// 當請求加載成功之后要調用指定的函數oReq.onload = function() {// 我現在需要得到這里的 oReq.responseTextcallback(oReq.responseText)}oReq.open("get", url, true)oReq.send()}</script></body> </html>3.用promise封裝ajax版:
<!DOCTYPE html> <html><head><meta charset="utf-8"><title></title></head><body><form action="#" id="user_form"></form><script type="text/text/template" id="tpl"><label for="">用戶名</label><input type="text" value="{{ user.username }}"><label for="">年齡</label><input type="text" value="{{ user.age }}"><label for="">職業</label><select name="" id="">{{ each jobs }}{{ if user.job === $value.id }}<option value="{{ $value.id }}" selected="selected">{{ $value.name }}</option>{{ else }}<option value="{{ $value.id }}">{{ $value.name }}</option>{{ /if }} {{ /each }}</select> </script><script src="node_modules/jquery/dist/jquery.js"></script><script src="node_modules/art-template/lib/template-web.js"></script><script>// 用戶表// 其中一個接口獲取用戶數據// 職業:1// 職業信息表// 其中一個接口獲取所有的職業信息/* get('http://127.0.0.1:3000/users/1', function(userData) {// data = JSON.parse(data)get('http://127.0.0.1:3000/jobs', function(jobsData) {// console.log(userData, jobsData)var htmlStr = template('tpl', {user: JSON.parse(userData),jobs: JSON.parse(jobsData)})console.log(htmlStr)document.querySelector('#user_form').innerHTML = htmlStr})}) */ /* var data = {}$.get('http://127.0.0.1:3000/users/1').then(function(userData) {console.log(userData)data.user = userDatareturn $.get('http://127.0.0.1:3000/jobs')}).then(function(jobsData) {console.log(jobsData)data.jobs = jobsDataconsole.log(data)var htmlStr = template('tpl', data)console.log(htmlStr)document.querySelector('#user_form').innerHTML = htmlStr}) */var data = {}get('http://127.0.0.1:3000/users/1').then(function(userData) {data.user = userDatareturn $.get('http://127.0.0.1:3000/jobs')}).then(function(jobsData) {data.jobs = jobsDatavar htmlStr = template('tpl', data)document.querySelector('#user_form').innerHTML = htmlStr }) function get(url) {return new Promise(function(resolve, reject) {var oReq = new XMLHttpRequest()// 當請求加載成功之后要調用指定的函數oReq.onload = function() {// 我現在需要得到這里的 oReq.responseTextresolve(JSON.parse(oReq.responseText))} oReq.onerror = function (err) {reject(err)}oReq.open("get", url, true)oReq.send()})}/* function get(url, callback) {var oReq = new XMLHttpRequest()// 當請求加載成功之后要調用指定的函數oReq.onload = function() {// 我現在需要得到這里的 oReq.responseTextcallback(oReq.responseText)}oReq.open("get", url, true)oReq.send()} */</script></body> </html>mongoose所有的API都支持Promise:
// 查詢所有 User.find().then(function(data){console.log(data)})注冊:
User.findOne({username:'admin'},function(user){if(user){console.log('用戶已存在')} else {new User({username:'aaa',password:'123',email:'fffff'}).save(function(){console.log('注冊成功');})} }) User.findOne({username:'admin' }).then(function(user){if(user){// 用戶已經存在不能注冊console.log('用戶已存在');}else{// 用戶不存在可以注冊return new User({username:'aaa',password:'123',email:'fffff'}).save();}}).then(funciton(ret){console.log('注冊成功');})Generator
async函數
總結
以上是生活随笔為你收集整理的Promise学习——解决回调地狱问题的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: echart 数据点可以加链接吗_地理可
- 下一篇: 二十、MySQL之用户权限管理(用户管理