Promise 基础 与 使用套路

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/felixking/article/details/79432370

Promise 是 ES6 中内置支持的对象

其构造函数接受一个参数, 该参数是一个函数, 该函数有两个参数, 两个参数都是函数, 一个在成功时调用(resolve), 一个在出错时调用(reject)

let myPromise = new Promise(
    function(resolve, reject){
        if (成功){
            resolve(数据 或 另一个 Promise);
        }else{
            reject(出错信息)
        }
    }
);

reject 的参数是 错误信息, 如网络异常, 或用户逻辑错误信息

resolve 的参数一般是 处理(如网络访问)后的数据, 也可以是 另一个 Promise

then 方法
Promise 的对象(如 myPromise) 可以调用 then 方法, then 方法 接受两个参数, 一个是 成功时的回调, 一个是出错时的回调

function resolved(数据){
};
function rejected(错误信息){
};
myPromise.then(resolved, rejected)

注意: 千万不要误解 是 Promise的参数 函数 中直接调用的 resolved 和 rejected, Promise的参数 函数 中的 resolve 方法 和 reject 方法 是 Javascript引擎实现的, 它们的作用是 修改 当前 Promise 的 状态 从 等待 到 成功完成 或是 从 等待 到 出错完成.
而 then 方法 做的是 设置一个 callback, 该 callback 会在 Promise 状态改变时 调用 then方法中给定的 resolved 或 rejected 参数函数

简单的例子

let promise = new Promise(function(resolve, reject){
    resolve("hello world");
});

promise.then(function(data){
    console.log(data);
})

输出:
hello world

复杂点的网络异步的例子

function fetchData(url){
    const promise = new Promise(function(resolve, reject){
        // 构造 一个 ajax 请求
        const client = new XMLHttpRequest();
        client.open("GET", url);
        client.onreadystatechange = function(){
            if (this.readyState != 4) { return; }
            if (this.status == 200){
                // 当网络请求成功时调用 resolve 方法, 并传入获取的数据
                resolve(this.response);
            }else{
                reject(new Error(this.statusText));
            }
        };;
        client.responseType = "json";
        client.setRequestHeader("Accept", "application/json");
        client.send();
    });
    return promise;
}

fetchData("data1.json").then(
    function(data){
        console.log(data);
    }   
)

上面then方法给定的 resolved 函数 只是简单的 打印了获得的数据

Javascript 引擎提供的 resolve 方法 可以接受 两种类型的参数
第一种参数是除了Promise对象之外的普通对象, 这时 resolve 方法 会修改 当前 Promise的状态 为 成功完成, 并将 这个 普通对象 作为 处理的结果保存, 将来 传递给 then 方法 的 参数 函数 resolved 作为参数
第二种参数是Promise 对象, 当 resolve 方法发现 参数是 一个 Promise 时, 并不会更改 当前 Promise的 状态, 而是 会 跟踪 参数Promise 的状态, 即 不会立刻就 导致 then 的 resolved 参数函数的触发, 而是会 等 参数Promise 的 状态变化时 才触发, 并且 then 的 resolved 函数的参数 由这个 新的 Promise 中的 resolve 方法 给定

let p1 = new Promise(
    function(resolve, reject){
        resolve("hello");
    }
)

let p2 = new Promise(
    function(resolve, reject){
        // 注: 并不会 改变 当前 Promise 的状态, 需要等待 p1 的执行结论
        resolve(p1);
    }
);

p2.then(function(data){
    console.log(data);
})

输出:
hello

这种 resolve Promise 的特性开发人员似乎不会直接用到

另外 then 参数方法 resolved 是可以有返回值的, 因为 then 方法的返回值是 一个 新的 Promise, 因此可以 链式调用
promise.then(function(data){})
.then(function(data){})
.then(function(data){})
.then(function(data){})
因此可以实现 阶段性的 异步调用, 如 先访问一个 url, 根据获得的数据 访问 另一个 url
这时就可以利用 resolved 的方法的返回值

let p = new Promise(
    function(resolve, reject){
        resolve(1);
    }
);

p.then(function(data){
    console.log(data);
    return 2
}).then(function(data){
    console.log(data);
    return 3
}).then(function(data){
    console.log(data);
}).then(function(data){
    console.log(data);
})
输出:
1
2
3
undefined

当返回值是一个 非 Promise 对象 的普通值, 则 then 返回的 Promise 直接就是 成功完成 的状态, 它的 then 方法 中的 resolve 方法 会被调用, 参数 就是 这个 普通值
当返回值是一个 Promise 对象, 则 then 方法 返回 的 Promise 对象 会 跟踪 该 Promise 对象的状态, 直到 这个 Promise 对象 的 状态 改变, 进而触发 then 的 resolve 方法 的调用

总结一下, then 方法 返回的 Promise 的 构造函数的参数函数 其实 是 resolve 了 then 方法 的 resolved 参数函数 的返回值, 这就是利用 之前那个特性实现的

function fetchData(url){
    const promise = new Promise(function(resolve, reject){
        const handle = function(){
            if (this.readyState != 4) { return; }
            if (this.status == 200){
                resolve(this.response);
            }else{
                reject(new Error(this.statusText));
            }
        };
        const client = new XMLHttpRequest();
        client.open("GET", url);
        client.onreadystatechange = handle;
        client.responseType = "json";
        client.setRequestHeader("Accept", "application/json");
        client.send();
    });
    return promise;
}

fetchData("data1.json").then(
    function(data){
        // 第一把结果获得
        console.log(data);
        // 业务没有完成, 继续发起请求
        return fetchData(data.nextURL)
    }
).then(
    function(data){
        // 第二把结果返回
        console.log(data);
    }
)

猜你喜欢

转载自blog.csdn.net/felixking/article/details/79432370
今日推荐