详解promise

promise是什么?

JavaScript 和 node 都是单线程非阻塞的运行方式,所以会出现一个异步回调的问题。promise就是为了解决这类问题 前端常见的异步操作有:

setTimeout setInterval ajax

现在基本都使用async和await

异步发展

callback

最初解决异步方式是通过callback回调去解决

例1:

let callback = () => {
    console.log('callback1');
}
setTimeout(callback, 1000)
console.log('begin');

// 打印顺序  
// begin 
// callback1
复制代码

例1是最典型的通过callback去解决异步问题, 但是有两个问题

1.无止境的回调,不利于代码维护如下,在ajax请求数据时尤其常见

2.好几个请求,很难同时得到数据(可以通过代码做到,比较烦)

promise + Q

为了解决上面两个问题出现了promise,用法如下

// Promise 是一个类通过new得到它的实例
// new Promise(executor) 传入的函数就是executor
let promise = new Promise((resolve, reject) => {
    // 传入一个方法,这个方法里面放的就是需要执行的异步程序 
    //这个方法有两个参数 resolve表示成功 reject表示失败 都是函数
    // 如果调用resolve会走then的第一个方法,即成功方法
    // 如果调用reject会走then的第二个方法,即失败方法 ,如果有报错也会走失败方法
    setTimeout(() => {
        console.log('2')
        resolve('resolveData')
        // reject('err')
    })
    console.log('1')
});
// 在Promise的原型上有一个then方法,会在primiose的executor执行后根据不同情况执行

promise.then((data) => {
    console.log(data)
    return data
}, (err) => {})

// 打印顺序 1 => 2 => 'resolveData'

// then方法在Promise内部是返回一个新的Promise实例,所以可以实现链式调用,并且将return出去的的值作为下一个then相应方法的参数

promise.then((data) => {
    console.log(data + '2')
    return data
}, (err) => {}).then((data) => {
    console.log(data)
}, () => {}) // 'resolveData' => 'resolveData2'

// 如果第一个then进入reject方法,但是在里面并没有报错,那么还是会进入下一个resolve方法,同样return出去的值也是第二个then相应方法的参数

复制代码

promise 常用方法

//catch 集体捕获错误
promise.then(() => {}).then(() => {}).catch(() => {})
// 不需要再每一个then里面都加上失败函数,可以选择在最后加上catch,如果失败或报错直接走到这

// Promise.all
let promise = new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve({a: 1});
    })
})
let promise1 = new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve({b: 2});
    })
})
let promise2 = new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve({c: 2});
    })
})

Promise.all([promise, promise1, promise2]).then((data) => {
    console.log('data', data); // data [ { a: 1 }, { b: 2 }, { c: 2 } ]
}, (err) => {
    console.log('err', err);
})
// 多个promise执行resolve后再走then第一个方法,有一个报错或执行reject直接走then第二个方法

// Promise.race 只要有一个promise成功了 就算成功。如果第一个失败了就失败了

Promise.race([promise, promise1, promise2]).then((data) => {
    console.log('data', data); // data { a: 1 }
}, (err) => {
    console.log('err', err);
})

// Promise.resolve  Promise.reject 分别返回一个成功 失败的promise
复制代码

Q库是一个promise的库,里面有all defer等方法,最后被node收购了,现在的promise也有all方法但是没有defer,很简单后面我们可以手写一个

generator + co

generator 函数需要用*来做表示,函数内部配合yield去暂停并且返回一个对象 { value: 1, done: false }

value的值是yield后面跟着的数值,

done的值是一个布尔类型,表示函数有没有执行完毕,false表示还没有执行完,可以继续通过it.next()调用;

function *mygenerator() {
    let m = yield 1
    console.log(m, '1'); // 22 '1'
    
    let n = yield 2
    console.log(n, '2'); // 33 '2'
}

let it = mygenerator(); // generator返回一个it值里面有一个next方法可以调用
console.log(it.next(11)); // { value: 1, done: false }
console.log(it.next(22)); // { value: 2, done: false }
console.log(it.next(33)); // { value: undefined, done: true }
复制代码

co库 npm install co 可以自动的将generator进行迭代

let co = require('co');
let co = require('co');

function *mygenerator() {
    let m = yield (() => { return {a: 1}})()
    console.log(m, '1'); // { a: 1 } '1'
    
    let n = yield (() => {return {b: 2}})()
    console.log(n, '2'); // { b: 2 } '2'

    return {m ,n}
}

co(mygenerator()).then((data) => {
    console.log('data', data) // data { m: { a: 1 }, n: { b: 2 } }
})

// 在使用co库时yield后面只能跟 function, promise, generator, array, or object 否则会报错
复制代码

async + await

async + await 就是 generator和co的语法糖 用法简单

async function r() {
    try{
        let m = await (() => { return {a: 1}})();
        let n = await (() => { return {a: 2}})();
        return {m, n};
    }catch(e){ // 如果出错会catch
        console.log('err',e)
    }
}

r().then((data) => {
    console.log('data', data);
})
复制代码

根据promiseA+实现一个自己promise

function Promise(executor) { // executor是一个执行函数
    let self = this;
    self.status = 'pending';
    self.value = undefined; // 默认成功的值
    self.reason = undefined; // 默认失败的原因
    self.onResolvedCallbacks = []; // 存放then成功的回调
    self.onRejectedCallbacks = []; // 存放then失败的回调
    function resolve(value) { // 成功状态
        if (self.status === 'pending') {
            self.status = 'resolved';
            self.value = value;
            self.onResolvedCallbacks.forEach(function (fn) {
                fn();
            });
        }
    }
    function reject(reason) { // 失败状态
        if (self.status === 'pending') {
            self.status = 'rejected';
            self.reason = reason;
            self.onRejectedCallbacks.forEach(function (fn) {
                fn();
            })
        }
    }
    try {
        executor(resolve, reject)
    } catch (e) { // 捕获的时候发生异常,就直接失败了
        reject(e);
    }
}
function resolvePromise(promise2, x, resolve, reject) {
    // 有可能这里返回的x是别人的promise
    // 尽可能允许其他乱写
    if (promise2 === x) { //这里应该报一个类型错误,有问题
        return reject(new TypeError('循环引用了'))
    }
    // 看x是不是一个promise,promise应该是一个对象
    let called; // 表示是否调用过成功或者失败
    if (x !== null && (typeof x === 'object' || typeof x === 'function')) {
        // 可能是promise {},看这个对象中是否有then方法,如果有then我就认为他是promise了
        try { // {then:1}
            let then = x.then;
            if (typeof then === 'function') {
                // 成功
                then.call(x, function (y) {
                    if (called) return
                    called = true
                    // y可能还是一个promise,在去解析直到返回的是一个普通值
                    resolvePromise(promise2, y, resolve, reject)
                }, function (err) { //失败
                    if (called) return
                    called = true
                    reject(err);
                })
            } else {
                resolve(x)
            }
        } catch (e) {
            if (called) return
            called = true;
            reject(e);
        }
    } else { // 说明是一个普通值1
        resolve(x); // 表示成功了
    }
}
Promise.prototype.then = function (onFulfilled, onRjected) {
    //成功和失败默认不穿给一个函数
    onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : function (value) {
        return value;
    }
    onRjected = typeof onRjected === 'function' ? onRjected : function (err) {
        throw err;
    }
    let self = this;
    let promise2; //返回的promise
    if (self.status === 'resolved') {
        promise2 = new Promise(function (resolve, reject) {
            // 当成功或者失败执行时有异常那么返回的promise应该处于失败状态
            // x可能是一个promise 也有可能是一个普通的值
            setTimeout(function () {
                try {
                    let x = onFulfilled(self.value);
                    // x可能是别人promise,写一个方法统一处理
                    resolvePromise(promise2, x, resolve, reject);
                } catch (e) {
                    reject(e);
                }
            })
        })
    }
    if (self.status === 'rejected') {
        promise2 = new Promise(function (resolve, reject) {
            setTimeout(function () {
                try {
                    let x = onRjected(self.reason);
                    resolvePromise(promise2, x, resolve, reject);
                } catch (e) {
                    reject(e);
                }
            })

        })
    }
    // 当调用then时可能没成功 也没失败
    if (self.status === 'pending') {
        promise2 = new Promise(function (resolve, reject) {
            // 此时没有resolve 也没有reject
            self.onResolvedCallbacks.push(function () {
                setTimeout(function () {
                    try {
                        let x = onFulfilled(self.value);
                        resolvePromise(promise2, x, resolve, reject);
                    } catch (e) {
                        reject(e)
                    }
                })
            });
            self.onRejectedCallbacks.push(function () {
                setTimeout(function () {
                    try {
                        let x = onRjected(self.reason);
                        resolvePromise(promise2, x, resolve, reject);
                    } catch (e) {
                        reject(e);
                    }
                })
            });
        })
    }
    return promise2;
}
// 捕获错误的方法
Promise.prototype.catch = function (callback) {
    return this.then(null, callback)
}
// 解析全部方法
// let arr = [];
// arr[1] = 100;
// console.log(arr.length)
Promise.all = function (promises) {
    //promises是一个promise的数组
    return new Promise(function (resolve, reject) {
        let arr = []; //arr是最终返回值的结果
        let i = 0; // 表示成功了多少次
        function processData(index, y) {
            arr[index] = y;
            if (++i === promises.length) {
                resolve(arr);
            }
        }
        for (let i = 0; i < promises.length; i++) {
            promises[i].then(function (y) {
                processData(i, y)
            }, reject)
        }
    })
}
// 只要有一个promise成功了 就算成功。如果第一个失败了就失败了
Promise.race = function (promises) {
    return new Promise(function (resolve, reject) {
        for (var i = 0; i < promises.length; i++) {
            promises[i].then(resolve,reject)
        }
    })
}
// 生成一个成功的promise
Promise.resolve = function(value){
    return new Promise(function(resolve,reject){
        resolve(value);
    })
}
// 生成一个失败的promise
Promise.reject = function(reason){
    return new Promise(function(resolve,reject){
        reject(reason);
    })
}
Promise.defer = Promise.deferred = function () {
    let dfd = {};
    dfd.promise = new Promise(function (resolve, reject) {
        dfd.resolve = resolve;
        dfd.reject = reject;
    });
    return dfd
}
// mjs
module.exports = Promise;
复制代码

有问题欢迎指正

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Promise.resolve 是一个在 JavaScript 中用来创建一个已经解决(resolved)的 Promise 对象的方法。它返回一个表示解决结果的 Promise 对象。 当传递给 Promise.resolve 的参数是一个包含 then 方法的对象时(称为 thenable 对象),Promise.resolve 方法会将该对象转换为一个 Promise 对象,并将其解决结果作为该 Promise 对象的解决值。如果传递给 Promise.resolve 的参数已经是一个 Promise 对象,则它会直接返回该对象,不做任何处理。 以下是 Promise.resolve 的示例用法: ```javascript // 创建一个已解决的 Promise 对象 const resolvedPromise = Promise.resolve("Resolved Value"); resolvedPromise.then(value => { console.log(value); // 输出 "Resolved Value" }); // 创建一个已解决的 Promise 对象,通过 thenable 对象 const thenable = { then(resolve) { resolve("Thenable Resolved Value"); } }; const resolvedThenable = Promise.resolve(thenable); resolvedThenable.then(value => { console.log(value); // 输出 "Thenable Resolved Value" }); // 返回传入的 Promise 对象 const existingPromise = new Promise(resolve => { resolve("Existing Promise Resolved Value"); }); const resolvedExistingPromise = Promise.resolve(existingPromise); resolvedExistingPromise.then(value => { console.log(value); // 输出 "Existing Promise Resolved Value" }); ``` 解释: Promise.resolve 方法的作用是将一个值转换为一个已解决的 Promise 对象。如果传入的值是一个 Promise 对象,那么 Promise.resolve 方法会直接返回该对象。如果传入的值是一个 thenable 对象,它会转换为一个 Promise 对象,并将其解决结果作为解决值。如果传入的值是一个非 thenable 对象,它会被包装在一个新的 Promise 对象中,并将其作为解决值。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值