function f1(callback){
callback();
}
function f2(callback){
callback();
}
function f3(callback){
callback();
}
f1(f2(f3))
複製代碼
這種方式實現異步編程優勢是思路清晰,以串行的思考方式進行編程,缺點是造成回調地獄,過多的回調嵌套使得代碼變得難以理解拆分和維護。es6
let dep = {
list: [],
on: function (fn) {
list.push(fn);
},
emit: function () {
this.list.forEach(event => {
typeof event === 'function' ? event() : null;
})
}
};
複製代碼
上面就是簡易版的發佈訂閱模式:發佈者存在一個數組list用於登記訂閱者即異步執行的函數,等到必定條件下執行emit,訂閱的異步函數都會執行。這就比如發佈者售樓中心的擁有一個登記冊,裏面登記須要買房的全部訂閱者,有的訂閱者登記的是電話通知,有的訂閱者登記的郵件通知,等到樓盤信息變化時會主動給每一個訂閱者執行相應的操做(執行對應的函數)編程
promise的核心原理其實就是發佈訂閱模式,經過兩個隊列來緩存成功的回調(onResolve)和失敗的回調(onReject)。若是還不熟悉promise用法的朋友,請參考Es6入門之promise對象,下面來分析promise的特色。數組
下面針對這些特色來實現promise:promise
function Promise (executor){
function resolve(value){}
function reject(value){}
try{
executor(resolve,reject);
}catch(e){
reject(e);
}
}
var promise = new Promise((resolve,reject)=>{
console.log('start');
})
複製代碼
function Promise (executor) {
var self = this;//resolve和reject中的this指向不是promise實例,須要用self緩存
self.state = 'padding';
self.value = '';//緩存成功回調onfulfilled的參數
self.reson = '';//緩存失敗回調onrejected的參數
self.onResolved = []; // 專門存放成功的回調onfulfilled的集合
self.onRejected = []; // 專門存放失敗的回調onrejected的集合
function resolve (value) {
if(self.state==='padding'){
self.state==='resolved';
self.value=value;
self.onResolved.forEach(fn=>fn())
}
}
function reject (reason) {
self.state = 'rejected';
self.value = reason;
self.onRejected.forEach(fn=>fn())
}
try{
executor(resolve,reject)
}catch(e){
reject(e)
}
}
複製代碼
Promise.prototype.then=function (onfulfilled,onrejected) {
var self=this;
if(this.state==='resolved'){
onfulfilled(self.value)
}
if(this.state==='rejected'){
onrejected(self.value)
}
if(this.state==='padding'){
this.onResolved.push(function () {
onfulfilled(self.value)
})
}
}
複製代碼
以上只是實現了promise的基本功能,可是還缺乏then的鏈式調用,then函數參數onfulfilled,onrejected缺省處理,鏈式調用返回值多種狀況的處理,下面分析then方法的特色:緩存
Promise.prototype.then=function (onfulfilled,onrejected) {
onfulfilled = typeof onfulfilled == 'function' ? onfulfilled : val => val;//onfulfilled缺省處理
onrejected = typeof onrejected === 'function' ? onrejected : err => {throw err;};//onrejected缺省處理
var self=this,promise2=new Promise(function(resolve,reject){//返回一個promise
if(this.state==='resolved'){
try{
onfulfilled(self.value);//裏面會執行resolve
}catch(e){
reject(e);
}
}
if(this.state==='rejected'){
try{
onrejected(self.value);
}catch(e){
reject(e);
}
}
if(this.state==='padding'){//將執行過程緩存
self.onResolved.push(function () {
try{
onfulfilled(self.value);
}catch(e){
reject(e)
}
});
self.onRejected.push(function () {
try{
onrejected(self.value);
}catch(e){
reject(e)
}
})
}
})
return promise2;
}
複製代碼
Promise.prototype.then=function (onfulfilled,onrejected) {
onfulfilled = typeof onfulfilled == 'function' ? onfulfilled : val => val;
onrejected = typeof onrejected === 'function' ? onrejected : err => {throw err;};
var self=this,
res=null,//用來緩存onfulfilled或onrejected的返回值
promise2=new Promise(function(resolve,reject){
if(this.state==='resolved'){
try{
res = onfulfilled(self.value);//獲得onfulfilled的返回值
resolvePromise(promise2,res,resolve,reject);//返回值的處理函數
}catch(e){
reject(e);
}
}
if(this.state==='rejected'){
try{
res = onrejected(self.value);//獲得onrejected的返回值
resolvePromise(promise2,res,resolve,reject);
}catch(e){
reject(e);
}
}
if(this.state==='padding'){
self.onResolved.push(function () {
try{
res = onfulfilled(self.value);
resolvePromise(promise2,res,resolve,reject);
}catch(e){
reject(e)
}
});
self.onRejected.push(function () {
try{
res = onrejected(self.value);
resolvePromise(promise2,res,resolve,reject);
}catch(e){
reject(e)
}
})
}
})
return promise2;
}
function resolvePromise(promise,res,resolve,reject) {
if(promise===res){//防止循環引用
return reject(new TypeError('循環引用'))
}
let called;//防止重複執行
if(res!==null&&(typeof res==='function'||typeof res ==='object')){
try {//防止promise執行報錯
let then=res.then;//判斷是否promise就判斷是否存在then方法
if(typeof then ==='function'){//若是返回的是promise,只須要在返回的promise的then方法中下一步須要執行的函數
then.call(res,(res2)=>{
if (called) return;
called = true;
resolvePromise(promise,res2,resolve,reject);//若是是promise繼續遞歸執行,直到不是promise,依次執行外層的resolve,讓promise狀態改變
},)
}else{//若是不是promise,有多是undefine、onfulfilled或onrejected的返回的普通值,就直接將這個值返回,將外層的promise狀態改變
if (called) return;
called = true;
resolve(then)
}
}catch(e){
if (called) return;
called = true;
reject(e)
}
}else{
resolve(res)
}
};
複製代碼
console.log(1);
var promise=new Promise(function(resolve,reject){
resolve('a');
})
promise.then(function(value){
console.log(value)
})
console.log(2);
// 1 2 'a'
複製代碼
//因爲promise有內部的機制實現微任務,因此這裏使用setTimeout代替
Promise.prototype.then=function (onfulfilled,onrejected) {
onfulfilled = typeof onfulfilled == 'function' ? onfulfilled : val => val;
onrejected = typeof onrejected === 'function' ? onrejected : err => {throw err;};
var self=this,
res=null,
promise2=new Promise(function(resolve,reject){
if(this.state==='resolved'){
setTimeout(()=>{
try{
res = onfulfilled(self.value);
resolvePromise(promise2,res,resolve,reject);
}catch(e){
reject(e);
}
})
}
if(this.state==='rejected'){
setTimeout(()=>{
try{
res = onrejected(self.value);
resolvePromise(promise2,res,resolve,reject);
}catch(e){
reject(e);
}
})
}
if(this.state==='padding'){
self.onResolved.push(function () {
setTimeout(()=>{
try{
res = onfulfilled(self.value);
resolvePromise(promise2,res,resolve,reject);
}catch(e){
reject(e);
}
})
});
self.onRejected.push(function () {
setTimeout(()=>{
try{
res = onrejected(self.value);
resolvePromise(promise2,res,resolve,reject);
}catch(e){
reject(e);
}
})
})
}
})
return promise2;
}
複製代碼
Promise.prototype.catch = function (onrejected) {
return this.then(null, onrejected)
};
複製代碼
Promise.reject = function (reason) {
return new Promise((resolve, reject) => {
reject(reason)
})
};
Promise.resolve = function (value) {
return new Promise((resolve, reject) => {
resolve(value);
})
};
複製代碼
//在每一個promise的回調中添加一個判斷函數processData(就是在當前的promise.then中添加),每一個promise狀態改變後讓index++,直到和promises的個數相等就執行回調
Promise.all=function (promises) {
return new Promise((resolve,reject)=>{
let results=[],i=0;
for(let i=0;i<promises.length;i++){
let p=promises[i];
p.then((data)=>{
processData(i,data)
},reject)
}
function processData (index,data) {
results[index]=data;
if(++i==promises.length){
resolve(results)
}
}
})
};
//在每一個promise的回調中添加一個resolve(就是在當前的promise.then中添加),有一個狀態改變,就讓race的狀態改變
Promise.race=function (promises) {
return new promises((resolve,reject)=>{
for(let i=0;i<promises.length;i++){
let p=promises[i];
p.then(resolve,reject)
}
})
};
複製代碼
Generator函數能夠經過yield暫停執行和next恢復執行,因此能夠封裝一個函數來自動執行next函數而使Generator完成異步任務。bash
let fs = require('mz/fs');
function * read() {
let age = yield fs.readFile('./name.txt','utf8');
let adress = yield fs.readFile(age,'utf8');
let r = yield fs.readFile(adress,'utf8');
return r;
}
function co(it) {//it爲一個generator對象
//返回一個promise而且執行generator對象的next
return new Promise((resolve,reject)=>{
function next(data) {
//獲取前一個異步函數的返回值,其必須爲promise
let { value, done } = it.next(data);
if(!done){
//返回promise的then方法中添加generator的next
//前一個異步函數執行成功會使返回的promise成resolved
//而後執行generator的next,遞歸依次類推
value.then(data=>{
next(data)
}, reject);
}else{
resolve(value);
}
}
next();
})
}
co(read()).then(data=>{
console.log(data);
},err=>{
console.log(err);
});
複製代碼
async+awit等於generator+co,而co中實現generator自動化是基於Promise,因此awit會使用new Promise形式。異步
若是以上有任何錯誤之處,但願提出並請指正,若是對promise使用還不清楚的朋友,請參考Es6入門之promise對象,本文參考:async