IFE 2019年04月11日 分类: 前端知识体系 标签: javascript 浏览量: 4090
Promise 对象用于表示一个异步操作的最终状态(完成或失败),以及该异步操作的结果值。它可以使我们以同步的方式写异步代码。
它只有三种状态:pending
(进行中)、fulfilled
(已成功)和rejected
(已失败)。 只有异步操作的结果,可以决定当前是哪一种状态,而且只能从pending
变为fulfilled
和从pending
变为rejected
。只要这两种情况发生,状态就凝固了,任何其他操作都无法改变这个状态。
Promise对象也是一个构造函数,可以用来生成Promise实例,它的语法是:
const promise = new Promise(function(resolve, reject) { // /* executor */ if (/* 异步操作成功 */){ resolve(value); } else { reject(error); } });
Promise构造函数接受一个函数(executor)作为参数,它会在Promise构造函数执行时被立即调用,该函数的两个参数分别是resolve
和reject
。它们是两个函数,由 JavaScript 引擎提供,不用自己部署。
Promise实例生成以后,可以用then
方法分别指定resolved状态和rejected状态的回调函数。then方法可以接受两个回调函数作为参数。第一个回调函数是Promise对象的状态变为resolved时调用,第二个回调函数是Promise对象的状态变为rejected时调用。其中,第二个函数是可选的,不一定要提供。这两个函数都接受Promise对象传出的值作为参数。
promise.then(function(value) { // success }, function(error) { // failure });
Promise.prototype.catch
方法是.then(null, rejection)
或.then(undefined, rejection)
的别名,用于指定发生错误时的回调函数。
promise.catch(function(error){ console.log(error) });
因为 Promise.prototype.then
和 Promise.prototype.catch
方法返回promise 对象, 所以它们可以被链式调用。
doSomething() // return promise .then(result => doSomethingElse(value)) .then(newResult => doThirdThing(newResult)) .then(finalResult => console.log(`Got the final result: ${finalResult}`)) .catch(failureCallback);
为了避免意外,即使是一个已经变成 resolve 状态的 Promise,传递给 then 的函数也总是会被异步调用:
Promise.resolve().then(() => console.log(2)); console.log(1); // 1, 2
传递到then中的函数被置入了一个微任务队列,而不是立即执行,这意味着它是在JavaScript事件队列的所有运行时结束了,事件队列被清空之后才开始执行:
const wait = ms => new Promise(resolve => setTimeout(resolve, ms)); wait().then(() => console.log(4)); Promise.resolve().then(() => console.log(2)).then(() => console.log(3)); console.log(1); // 1, 2, 3, 4
返回一个 Promise 实例,在参数内所有的 promise 都“完成(resolved)”或参数中不包含 promise 时回调完成(resolve);如果参数中 promise 有一个失败(rejected),此实例回调失败(reject),失败原因的是第一个失败 promise 的结果。
const promise1 = Promise.resolve(3); const promise2 = 42; const promise3 = new Promise(function(resolve, reject) { setTimeout(resolve, 100, 'foo'); }); Promise.all([promise1, promise2, promise3]).then(function(values) { console.log(values); }); // expected output: Array [3, 42, "foo"]
返回一个 Promise,它将与参数中第一个传递的 promise 相同的完成方式被完成。它可以是完成( resolves),也可以是失败(rejects),这要取决于第一个完成的方式是两个中的哪个。 如果传的迭代是空的,则返回的 promise 将永远等待。
var p1 = new Promise(function(resolve, reject) { setTimeout(resolve, 500, "one"); }); var p2 = new Promise(function(resolve, reject) { setTimeout(resolve, 100, "two"); }); Promise.race([p1, p2]).then(function(value) { console.log(value); // "two" // 两个都完成,但 p2 更快 });
返回一个以给定值解析后的Promise 对象。
var original = Promise.resolve('我在第二行'); var cast = Promise.resolve(original); cast.then(function(value) { console.log('value: ' + value); }); console.log('original === cast ? ' + (original === cast)); /* * 打印顺序如下,这里有一个同步异步先后执行的区别 * original === cast ? true * value: 我在第二行 */
返回一个带有拒绝原因reason参数的Promise对象。
Promise.reject("Testing static reject").then(function(reason) { // 未被调用 }, function(reason) { console.log(reason); // "Testing static reject" }); Promise.reject(new Error("fail")).then(function(result) { // 未被调用 }, function(error) { console.log(error); // stacktrace });
返回一个Promise,在promise执行结束时,无论结果是fulfilled或者是rejected,在执行then()和catch()后,都会执行finally指定的回调函数。
由于无法知道promise的最终状态,所以finally的回调函数中不接收任何参数,它仅用于无论最终结果如何都要执行的情况。
let isLoading = true; fetch(myRequest).then(function(response) { var contentType = response.headers.get("content-type"); if(contentType && contentType.includes("application/json")) { return response.json(); } throw new TypeError("Oops, we haven't got JSON!"); }) .then(function(json) { /* process your JSON further */ }) .catch(function(error) { console.log(error); }) .finally(function() { isLoading = false; });
可以用async声明一个异步函数,这个函数会返回一个promise,使用awiat可以让语法更加同步。当这个 async 函数返回一个值时,Promise 的 resolve 方法会负责传递这个值;当 async 函数抛出异常时,Promise 的 reject 方法也会传递这个异常值。
await 表达式,会使 async 函数暂停执行,等待 Promise 的结果出来,然后恢复async函数的执行并返回解析值(resolved)。await只能接一个promise。
注意, await 关键字仅仅在 async function中有效。如果在 async function函数体外使用 await ,你只会得到一个语法错误(SyntaxError)。
async function foo() { try { let result = await doSomething(); let newResult = await doSomethingElse(result); let finalResult = await doThirdThing(newResult); console.log(`Got the final result: ${finalResult}`); } catch(error) { failureCallback(error); } }
使用try catch 也因为它相比promise.then更像同步代码.这是发明这个语法的初衷