then的用法
需求: 分段讀取,第一個(gè)的輸出是下一個(gè)的輸入
let fs = require('fs');
缺陷: 1.不好維護(hù),回調(diào)嵌套 2.異步錯(cuò)誤處理不能統(tǒng)一
fs.readFile('./name.txt','utf8',function(err,data){
fs.readFile(data,'utf8',function(err,data){
console.log(data);
})
})
變成promise
function read(url) {
return new Promise((resolve,reject)=>{
fs.readFile(url,'utf8',function(err,data){
if(err) reject(err)
resolve(data);
})
})
}
// promise執(zhí)行,并且采用它的狀態(tài),如果成功會(huì)將成功的結(jié)果向外層的下一個(gè)then傳遞
read('./name.txt').then((data)=>{
//return read(data)
return read(data+1) //錯(cuò)誤
},(err)=>{
console.log(err)
}).then((data)=>{
console.log(data)
},(err)=>{
console.log(err);
return false // 如果返回的是一個(gè)普通值 那么會(huì)將這個(gè)值作為下一次的成功的結(jié)果
}).then((data)=>{
console.log(data) //false
// 希望在這里不要再繼續(xù)向下走then
// throw now Error() 錯(cuò)誤也會(huì)走到外層錯(cuò)誤中
return new Promise(()=>{}); // 終止promise 可以返回一個(gè)pending的promise
},(err)=>{
console.log(err);
}).then((data)=>{
console.log('success')
},(err)=>{
console.log('erroe');
})
// 總結(jié)
// 1. 只有兩種情況會(huì)失敗 返回一個(gè)失敗的promise 或者拋出異常
// 2. 每次執(zhí)行promise的時(shí)候,都會(huì)返回一個(gè)新的promise實(shí)例
then.js
1.(then中傳遞的函數(shù))判斷成功和失敗函數(shù)的返回結(jié)果
2.判斷是不是prmise 如果是promise就采取它的狀態(tài)
3.如果不是promise 直接將結(jié)果傳遞下去
let Promise = require('./promise')
let p1 = new Promise((resolve, reject) => {
resolve(1000);
})
let p2 = p1.then((data) => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(new Promise((resolve, reject) => {
resolve(1000)
}))
}, 0)
});
// return new Promise((resolve, reject) => {
// setTimeout(() => {
// resolve('hhh')
// }, 0)
// });
// throw new Error('錯(cuò)了')
},(err) => {
console.log(err)
})
let p3 = p2.then((data) => {
console.log('11', data);
return 3
},(err) => {
console.log(1, err)
})
p3.then((data) => {
console.log('22', data)
},(err) => {
console.log(2, err)
})
//問題一 x和promise2是一個(gè)的情況
// let promise = new Promise((resolve, reject) => {
// resolve();
// })
// let promise2 = promise.then(() => {
// return promise2;
// })
// promise2.then(null, (err) => {
// console.log(err) //會(huì)打印 Chaining cycle detected for promise #<Promise>
// })
promise.js
const PENDING = 'PENDING' //等待態(tài)
const FULFILLED = 'FULFILLED' //成功態(tài)
const REJECTED = 'REJECTED' //失敗態(tài)
// 因?yàn)樗械膒romise,都遵循這個(gè)規(guī)范, 規(guī)定 這里這個(gè)寫法應(yīng)該兼容所有的promise
let resolvePromise = (promise2, x, resolve, reject) => {
// 判斷x值
// promise和x不能是一個(gè)(自己等著自己去在做事),如果是一個(gè)就直接拋錯(cuò)
if(promise2 === x) {
return reject(new TypeError('Chaining cycle detected for promise #<Promise>'))
}
if(typeof x === 'object' && x !== null || typeof x === 'function') {
let called; // 內(nèi)部測(cè)試的時(shí)候會(huì)成功和失敗都調(diào)用
try {
let then = x.then; // 取then 報(bào)錯(cuò)原因:有可能這個(gè)then屬性通過(guò)Object.defineProperty來(lái)定義的
if(typeof then === 'function') { // 當(dāng)前有then方法 認(rèn)為是一個(gè)promise
then.call(x, y => {
if(called) {
return
}
called = true; // 防止多次調(diào)用成功和失敗
// resolve(y); // 采取promise的成功結(jié)果將值向下傳遞
resolvePromise(promise2, y, resolve, reject); // y可能還是一個(gè)promise, 遞歸resolvePromise,直到解析出一個(gè)普通值為止
}, r => {
if(called) {
return
}
called = true;
reject(r) // 采取失敗結(jié)果向下傳遞
}) // 能保證不用再次取then的值
} else {
resolve(x) //說(shuō)明x 是一個(gè)普通的對(duì)象 直接成功即可
}
} catch (e) {
// 失敗了 有可能還能調(diào)成功
if(called) {
return
}
called = true;
reject(e)
}
} else {
// x 是個(gè)普通值 直接讓promise2成功即可
resolve(x)
}
}
class Promise {
constructor(executor){
this.state = PENDING; 默認(rèn)等待態(tài)
this.value = undefined;
this.reason = undefined;
this.OnResolvedCallbacks = []; // 存放成功時(shí)的回調(diào)
this.OnRejectedCallbacks = []; // 存放失敗時(shí)的回調(diào)
// 只有狀態(tài)是等待態(tài)時(shí) 才可以更新狀態(tài)
let resolve = (value) {
if(this.status === PENDING) {
this.status = FULFILLED
this.value = value
this.OnResolvedCallbacks.forEach(fn=>fn()); //發(fā)布的過(guò)程
}
}
let reject = (reason) {
if(this.status === PENDING) {
this.status = REJECTED
this.reason = reason
this.OnRejectedCallbacks.forEach(fn=>fn()); //發(fā)布的過(guò)程
}
}
// executor 執(zhí)行的時(shí)候 需要傳入兩個(gè)參數(shù),給用戶改變狀態(tài)
try {
executor(resolve, reject)
} catch (e) {
reject(e) //表示當(dāng)前有異常,那就使用這個(gè)異常作為promise失敗的原因
}
}
then(onFulfilled, onRejected){ // then方法就是異步的
// 首先判斷兩個(gè)參數(shù)是否為函數(shù)類型,因?yàn)閮蓚€(gè)參數(shù)時(shí)可選參數(shù)
onResolved = typeof onResolved === 'function'? onResolved:(data)=>data
onRejected = typeof onRejected === 'function'? onRejected:(err)=>{
throw err
}
let promise2 = new Promise((resolve,reject)=>{ // executor 會(huì)立刻執(zhí)行
if(this.status === FULFILLED){
// 定時(shí)器是因?yàn)閞esolvePromise能拿到promise2
// try...catch..是因?yàn)楫惒酱a無(wú)法被外部try...catch..捕獲
setTimeout(()=>{
try {
let x = onFulfilled(this.value)
// x 可能是promise ,也可能是普通值
// 判斷x的值 =》 promise2的狀態(tài)
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e)
}
},0)
}
if(this.status === REJECTED){
setTimeout(()=>{
try {
let x = onRejectrd(this.reason)
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e)
}
},0)
}
// 異步情況
if(this.status === PENDING){
// 先訂閱
this.OnResolvedCallbacks.push(()={
// todo
setTimeout(()=>{
try {
let x = onFulfilled(this.value)
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e)
}
},0)
})
this.OnRejectedCallbacks.push(()={
setTimeout(()=>{
try {
let x = onRejectrd(this.reason)
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e)
}
},0)
})
}
})
return promise2;
}
}
Promise.defer = Promise.deferred = function () {
let dfd = {};
dfd.Promise = new Promise((resolve, reject) => {
dfd.resolve = resolve;
dfd.reject = reject;
})
return dfd
}
module.exports = Promise
dfd.js
let Promise = require('./promise');
let fs = require('./fs');
// Promise.defer() 可以解決封裝嵌套的問題
function read(url) {
// return new Promise((resolve, reject) => {
fs.reafFile(url, 'utf8', function(err, data) {
if(err) dfd.reject(err);
dfd.resolve(data);
})
return dfd.promise
// })
}
read('./name.txt').then(data => {
console.log(data)
})
all.js
// Promise.all 可以實(shí)現(xiàn)等待所有的異步執(zhí)行完后 拿到統(tǒng)一結(jié)果
// 解決異步并發(fā) 同步處理結(jié)果
let Promise1 = require('./promise');
let fs = require('fs');
// Promise.defer() 可以解決封裝嵌套的問題
function read(url) {
// return new Promise((resolve, reject) => {
let dfd = Promise1.defer();
fs.readFile(url, 'utf8', function(err, data) {
if(err) dfd.reject(err);
dfd.resolve(data);
})
return dfd.promise
// })
}
const isPromise = (value) => {
if(typeof value === 'object' && value !== null || typeof value === 'function') {
if( typeof value.then === 'function') {
return true;
}
} else {
return false;
}
}
Promise.all = function(values) {
return new Promise((resolve, reject) => {
let arr = [];
let index = 0; // 解決多個(gè)異步并發(fā)問題 要使用計(jì)數(shù)器
function processData(key, value) {
arr[key] = value;
if(++index === values.length) {
resolve(arr)
}
}
for(let i = 0; i< values.length; i++) { //let
let current = values[i];
if(isPromise(current)) {
current.then((data) => {
processData(i, data);
},reject)
} else {
processData(i, current)
}
}
})
}
// all 類方法(靜態(tài)方法)返回promise 全部成功才成功, 任何一個(gè)失敗就失敗了
Promise.all([1, 2, 3, read('./name.txt'), 4,5]).then(data => {
console.log(data) // [ 1, 2, 3, name, 4, 5 ]
})
finally.js
// finally 最終的 try catch finally es9// node9
let p = new Promise((resolve, reject) => {
resolve(100);
// reject(100)
});
Promise.prototype.finally = function(cb) {
return p.then(data => {
// Promises.resolve() 可以等待promise執(zhí)行完成
return Promise.resolve(cb().then(() => data))
// cb(); // finally 傳入的函數(shù) 無(wú)論成功還是失敗都會(huì)執(zhí)行
// return data // 如果是成功 會(huì)走到下一個(gè)成功里
}, err => {
return Promise.resolve(cb().then(() => {
throw err;
}))
// cb();
// throw err;
})
}
// Promise.prototype.finally = function(cb) {
// return p.then(
// data => Promise.resolve(cb().then(() => data)),
// err => Promise.resolve(cb().then(() => {
// throw err;
// }))
// )
// }
p.finally(() => { // 返回的是一個(gè)promise實(shí)例
console.log('最終的')
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve();
}, 3000)
})
}).then(data => {
console.log(data)
}).catch(e => {
console.log(e)
})
// 1) 如果放的普通值會(huì)將這個(gè)值包裝成promise, 如果放的是promise 會(huì)等待這個(gè)promise執(zhí)行完后再繼續(xù)執(zhí)行
Promise.resolve(1).then(data => {
console.log(data)
})
// 1)用2)理解3)編寫
//Promise.reject
// Promise.race
// Promise.catch
// Promise.try