天天看點

promise 原理

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
TEST PROMISE
<div>
    <h1>promise 原理</h1>
    <p>
        Promise 是一個構造函數:
    <ul>
        <li>Promise:接受一個執行函數</li>
        <li>執行函數裡面兩個形參:resolve,reject</li>
        <li>
            <p>Promise的原型上面有個then方法,這個方法接受兩個參數(resolveCallback,rejectCallback)</p>
            <p>并且把這個兩個方法儲存到promise的一個回調數組裡面,當執行resolve的時候,根據status執行對應的回調方法</p>
            <p>如果需要鍊式回調,則在then方法裡面,傳回一個新的promise對象,在回調數組裡面儲存resolveCallback,rejectCallback,和新的promise對象的resolve,reject方法</p>
            <p>然後在resolve方法裡面執行回調數組裡面的resolve方法</p>
        </li>
    </ul>
    </p>
</div>
</body>
<script>
    function MyPromise(fn) {
        var _this = this
        _this.value = null; // resolve,reject的值
        _this.status = 'Pending' // promise 的狀态,Pending:初始,Fulfilled:resolve,Rejected:reject

        _this.deffers = [] // 回調數組每調用一次then,就萬裡面push一個{onFullFilled:onFullFilled,onRejected:onRejected}
        function resolve(val) {
            if (_this.status === 'Pending') {
                _this.status = 'Fulfilled'
                _this.value = val
                _this.deffers.forEach(function (item) {
                    var res;
                    var onFullFilled = item.cb
                    var resolve = item.resolve
                    onFullFilled && (res = onFullFilled(_this.value))
                    if (typeof res === 'object' && res.then) {
                        res.then(resolve)
                    }else {
                        resolve && resolve(res)
                    }
                })
            }
        }
        function reject(val) {
        }
        fn(resolve,reject)

    }
    MyPromise.prototype.then = function (onFullFilled,onRejected) {
        var _this = this
        return new MyPromise(function (resolve,reject) {
            _this.deffers.push({
                cb:onFullFilled,
                resolve:resolve
            })
        })
    }

    var a = new MyPromise(function (reslove,reject) {
        setTimeout(function () {
            reslove('success')
            reject('fail')
        }, 1000);
    })
    a.then(function (res) {
        console.log(res)
        return (888)
    }).then(function (res) {
        console.log(9999)
    })
</script>
</html>