Взгляните на принцип ОБЕЩАНИЯ, не бойтесь!

внешний интерфейс Promise Ajax

В повседневной работе фронтальной работы функция обратного вызова не должна не удивлена, но когда функция обратного вызова столкнулась с ASYNC (ASYNC), это возмутительно. Так что же означает асинхронный? Проще говоря, это означает, что код ниже будет выполнен, прежде чем закончить его выполнение.

Например 🌰:

Наша наиболее часто используемая асинхронная операция должна быть ajax (я думаю, что когда я впервые использовал ajax, это была катастрофа. Очевидно, что ресурс был успешно загружен, почему данные не передаются в ресурс? Это действительно раздражает.) можно только дождаться завершения загрузки, а затем выполнить соответствующие операции для достижения успеха. Таким образом, весь код, который мы видим, должен выглядеть так.

/**
@param callback 回调函数
*/
function getData(url,callback){
    $.ajax({
        url:url,
        success:function(result){
            callback(result);
        }
    });
}
//假设我有好多个ajax,每个ajax都需要上一个ajax的支持,于是……地狱出现了……
getData(url1,function(res){
    getData(url2,function(res){
        getData(url3,function(res){
            //终于可以干正事了
        })
    })
})

Друзья, поймите callback hell.

Итак, обещание появилось, и его появление решило ад обратных вызовов! Он инкапсулирует асинхронные функции и превращает обратные вызовы в связанные вызовы.

Например 🌰:

function getData(url){
    return new Promise((resolve,reject)=>{
$.ajax({
        url:url,
        success:function(result){
            resolve(result);
        },
        error:function(error){
            reject(error);
        }
    });
    })
}
getData(url1).then(function(res){
    return getData(url2)
}).then(function(res){
    return getData(url3)
}).then(function(res){
    //干正事啦!
})

В самом деле. Это намного проще, по крайней мере, скобки на трех внутренних слоях и трех внешних слоях не спутают.

Но когда я услышал обетование, я отверг его в своем сердце. Хоть я и отказываюсь в сердце своем, но то, что должно прийти, все равно должно прийти, а тому, чему следует научиться, еще предстоит научиться, ведь время идет, а идти в ногу со временем еще надо! Так как же выполняется это обещание? ? ?

Реализация 1: Статус

Друзья, обещайте здесь не романтическую строчку «Обещаю ХХХ» в знакомствах между мужчинами и женщинами, а норму.Щелкните здесь, чтобы ознакомиться со спецификациями. Однако обещание здесь, как и обещание в реальной жизни, имеет три состояния: выполнено, отклонено и ожидает исполнения.

Например 🌰:

Предположим, Мэри и Майк - пара.Полгода назад Майк пообещал Мэри завершить их свадьбу в течение полугода, но Майк до сих пор не предпринял никаких действий, поэтому Мэри сказала, что не будет заставлять ждать (в ожидании), поэтому Они распались, то обещание было отклонено. Если Майк и Мэри поженятся в течение шести месяцев, Майк уже должен был выполнить свое обещание, данное Мэри.

Итак, у всех промисов есть состояние результата — выполнено или отклонено, и состояние перед результатом — ожидание.

p1.js

//p1.js
function Promise(executor){
    let _=this;
    _.value=undefined;
    _.reason=undefined;
    _.state="pending"//大家一开始都是一样,等着吧
    function resolve(value){
        _.value=value//实现之后的感言
        _.state="fulfilled"//实现啦!
    }
    function reject(reason){
        _.reason=reason //给我一个被拒绝的理由
        _.state="rejected" //被拒绝了!
    }
    executor(resolve,reject)
}

//e.g
let Iagree=new Promise((resolve,reject)=>{
    resolve("我开心就同意了");//
})
let Idisagree=new Promise((resolve,reject)=>{
    reject("我不开心就拒绝了");
})
let noResult=new Promise((resolve,reject)=>{
})
console.log(Iagree.state,Idisagree.state,noResult.state)

Реализация 2: добавьте функцию then

Но я знаю только, что толку от одного состояния? Я должен перейти к следующему шагу! нам нужноthen, для следующего шага.

p2.js

//p2.js
Promise.prototype.then=function(onFulfilled, onRejected){
    let _=this;
    if(_.state=="pending"){}
    if(_.state=="fulfilled"){
        onFulfilled(_.value)
    }
    if(_.state=="rejected"){
        onRejected(_.reason)
    }
}
//e.g
let Iagree=new Promise((resolve,reject)=>{
    resolve("我开心就同意了");//强行完成(fullfilled)
})
Iagree.then((data)=>{
    console.log(Iagree.state)
},(e)=>{
    console.log(e)
})

Реализация 3: реализовать асинхронное выполнение

Однако это делается одновременно, а не асинхронно. Давайте посмотрим на асинхронность ~

В это время нам нужно передать функцию обратного вызова в разрешение или отклонение, но что, если у нас есть много последующих методов? потом сколько раз делать! Бросьте callback в очередь, и тогда Foreach будет выполняться один за другим.

p3.js

//p3.js
function Promise(executor){
    //....
    _.resolveCallbacks=[];//callbacks在pending中添加,fullfilled中执行
    _.rejectCallbacks=[];//callbacks在pending中添加,rejected中执行
    function resolve(value){
        //....
        _.resolveCallbacks.forEach((fn)=>fn())
    }
    function reject(reason){
       //....
        _.rejectCallbacks.forEach((fn)=>fn())
    }
    //....
}
Promise.prototype.then=function(onFulfilled, onRejected){
    let _=this;
    if(_.state=="pending"){
        //把回调方法塞进队列中
        _.resolveCallbacks.push(()=>{
            onFulfilled(_.value)
        })
        _.rejectCallbacks.push(()=>{
            onRejected(_.reason)
        })
    }
    //....
}
//e.g
let Iagree=new Promise((resolve,reject)=>{
    setTimeout(()=>{
        resolve("我开心就同意了");
    },1000)
})

//为了防止多次then,所以回调方法需要丢入队列中,防止方法被覆盖。
Iagree.then((data)=>{
    console.log(Iagree.state)
},(e)=>{
    console.log(e)
})
Iagree.then((data)=>{
    console.log(Iagree.state+1)
},(e)=>{
    console.log(e)
})

Реализация 4: реализация цепочек вызовов

Так что вопрос в том, если я прямо тогда, я могу? Так:

Iagree.then((data)=>{
    ...
}).then((data)=>{
    ...
}).then((data)=>{
    ...
})

Если вы хотите написать так, то предыдущий шагthenВы должны вернуть объект обещания, в противном случае вы можете изменить егоthenметод. Поэтому нам нужноthenсерединаnewновое обещание для следующего связанного вызоваthen.

p4.js

//p4.js
function resolvePromise(promise,x,resolve,reject){
    //如果x可能是一个promise
    if(x!==null&&(typeof x==="object"||typeof x==="function")){ 
        let then=x.then;
        //如果x是一个promise,因为promise都要有then函数的
        if(typeof then === "function"){
            //y表示x这个promise的值
            then.call(x,y=>{
                //继续遍历,直至返回值不是promise
                resolvePromise(promise,y,resolve,reject)
            },err=>{
                reject(err)
            })
        }else{
            //如果x是个普通对象,直接运行
            resolve(x)
            }
    }else{
        //如果x不是一个promise,也就是x是一个常量,直接运行
        resolve(x)
    }
}
Promise.prototype.then=function(onFulfilled, onRejected){
    let _=this;
    let promise2;
    //将当前promise的值传递到下一次then的调用中
    function resolveFunction(promise,resolve,reject){
        let x=onFulfilled(_.value)
        resolvePromise(promise,x,resolve,reject)
    }
    function rejectFunction(promise,resolve,reject){
        let x=onRejected(_.reason)
        resolvePromise(promise,x,resolve,reject)
    }
    promise2=new Promise((resolve,reject)=>{
        if(_.state=="pending"){
            //把回调方法塞进队列中
            _.resolveCallbacks.push(()=>{
                resolveFunction(promise2,resolve,reject)
            })
            _.rejectCallbacks.push(()=>{
                rejectFunction(promise2,resolve,reject)
            })
        }
        if(_.state=="fulfilled"){
            resolveFunction(promise2,resolve,reject)
        }
        if(_.state=="rejected"){
            rejectFunction(promise2,resolve,reject)
        }
    })
    return promise2
}
//e.g
let Iagree=new Promise((resolve,reject)=>{
    setTimeout(()=>{
        resolve("我开心就同意了");
    },1000)
})

//为了防止多次then,所以回调方法需要丢入队列中,防止方法被覆盖。
Iagree.then((data)=>{
    console.log(data)
    return new Promise((resolve,reject)=>{
        setTimeout(()=>{
            resolve("看心情干活");
        },1000)
    })
}).then((data)=>{
    console.log("前方返回一个promise:"+data)
    return data+",我是一个常量"
}).then((data)=>{
    console.log("常量返回:"+data)
}).then((data)=>{
    console.log("前方无法返回:"+data)
})

Таким образом, мы можем счастливо связывать промисы, о чем приятно подумать. Однако вышеописанное — это всего лишь простой и грубый способ реализации промисов, всего лишь принцип, и некоторые спецификации промисов нуждаются в доработке.Щелкните здесь, чтобы ознакомиться со спецификациями.

Соответствует спецификации promisesA+

Обобщить несколько пунктов

  • Долженtry{}catch(){}Все места отмечены, я скорее убью по ошибке, чем отпущу.
  • Методы onFulfilled и onRejected помещаются вsetTimeoutВ том числе, чтобы превратить их в «макрозадачи». (Это должно быть сделано из соображений производительности и будет изучено позже.)
  • затем добавьтеPromise.defer = Promise.deferred = function(){}метод предотвращения несанкционированного доступа.
  • Затем экспортируйте обещание,module.exports=Promise.
  • Последний прогонpromises-aplus-tests.cmd 你的promise.js, затем пройдите свой код построчно, подождите, пока все не станет зеленым (прохождение), поздравляем с успешным завоеванием промиса! !

p5.js

//参考p5.js