企业🤖AI智能体构建引擎,智能编排和调试,一键部署,支持私有化部署方案 广告
# 为什么用 Promise 调用 API 如下载文件,读取文件一些平时你会执行的异步操作而不使用同步操作。因为服务器可能会性能下降,响应慢等等问题,你不希望因为等待着结果,让整个进程都被堵住。比如下面模拟远程求两个数之和: ~~~ // 远程相加两数字,调用 API 获得结果 ​ function addAsync (num1, num2, callback) {    //使用有名的 jQuery getJSON 的回调 API    return $.get('http://www.example.com', {        num1: num1,        num2: num2   }, callback); } ​ addAsync(1, 2, function(data) {    const result = data; // 这里你得到 result = 3    console.log(result); }); ~~~ 这个语法看上去 OK,但想一系列的异步操作怎么办?比如说,不同于一次仅仅相加两个数字,我们希望加 3 次,即下次运算用到上次计算的结果。 ~~~ let resultA, resultB, resultC; ​ function addAsync (num1, num2, callback) {    return $.get('http://www.example.com', {        num1: num1,        num2: num2   }, callback); } ​ addAsync(1, 2, function(data) {    // callback 1    resultA = data; // you get result = 3 here ​    addAsync(resultA, 3, function(data1) {        // callback 2        resultB = data1; // you get result = 6 here ​        addAsync(resultB, 4, function(data2) {            // callback 3            resultC = data2; // you get result = 10 here            console.log('total' + resultC);            console.log(resultA, resultB, resultC);       });   }); }); ~~~ 这个语法很不友好。更贴切地说,这个看上去像金字塔,人们经常称呼为 "回调地狱",因为一个回调嵌在另一个回调之中。若你还觉得没有问题,可以想象有 10 个回调,这代码得嵌套 10 次! # Promise Promise 是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大。说直白点就是 Promise 就是一种写代码的方式,并且是用来写 JavaScript 编程中的异步代码的。它由社区最早提出和实现,ES6 将其写进了语言标准,统一了用法,原生提供了 Promise 对象。 有了 Promise 对象,就可以将异步操作以同步操作的流程表达出来,避免了层层嵌套的回调函数。此外,Promise 对象提供统一的接口,使得控制异步操作更加容易。 一个 Promise 对象 有以下几种状态: * pending: 初始状态,既不是成功,也不是失败状态。 * fulfilled: 意味着操作成功完成。 * rejected: 意味着操作失败。 !\[\](file://D:/H5%E5%AD%A6%E7%A7%91%E5%8D%81%E4%B9%9D%E6%9C%9F%E8%AF%BE%E7%A8%8B/nodejs-prosime07/img/promise%E7%8A%B6%E6%80%81%E5%8F%98%E5%8C%96.png?lastModify=1570810183) # 基本用法 构造实例: * 构造函数接受一个函数作为参数; * 调用构造函数得到实例 p 的同时,作为参数的函数会立即执行; * 参数函数接受两个回调函数参数 resolve 和 reject; * 在参数函数被执行的过程中,**若在其内部调用 resolve,会将 p 的状态变成 fulfilled,或者调用 reject,会将 p 的状态变成 rejected**。 调用 then: * 调用 then 可以为实例 p 注册两种状态回调函数; * 当实例 p 的状态为 fulfilled,会触发第一个函数执行; * 当实例 p 的状态为 rejected,则触发第二个函数执行。 调用 catch: * 调用 catch 用于注册 rejected 状态的回调函数,同时该回调也是程序出错的回调,即如果前面的程序运行过程中出错,也会进入执行该回调函数。 ~~~ var isMomHappy = false; // Promise var p = new Promise(    function (resolve, reject) {        if (isMomHappy) {            var phone = {                brand: 'Samsung',                color: 'black'           };            resolve(phone); // 完成了       } else {            var reason = new Error('妈妈不开心');            reject(reason); // reject       }   } ); ​ p.then(function (fulfilled) {        // 太好啦, 你获得了一个新手机        console.log(fulfilled);        // output: { brand: 'Samsung', color: 'black' }   })   .catch(function (error) {        // 好不幸,你妈妈没买手机        console.log(error.message);        // output: '妈妈不开心'   }); ~~~ # 使用 Promise 改造 AJAX ~~~ let request = obj => {    return new Promise((resolve, reject) => {        let xhr = new XMLHttpRequest();        xhr.open(obj.method || "GET", obj.url);        if (obj.headers) {            Object.keys(obj.headers).forEach(key => {                xhr.setRequestHeader(key, obj.headers[key]);           });       }        xhr.onload = () => {            if (xhr.status >= 200 && xhr.status < 300) {                resolve(xhr.response);           } else {                reject(xhr.statusText);           }       };        xhr.onerror = () => reject(xhr.statusText);        xhr.send(obj.body);   }); }; ​ request({url: "employees.json"})   .then(data => {        console.log(data);   })   .catch(error => {        console.log(error);   }); ~~~