
构建不确定Promise
一般情况下使用Promise构造函数创建新的Promise。这个构造函数接受一个参数:一个称为 executor 的函数,它包含初始化 promise 的代码。执行器被传递了两个名为resolve() 和reject() 的函数作为参数。 当 executor 成功完成时调用 resolve() 函数表示 promise操作成果,或者调用 reject() 函数表示操作失败。
下面是一个使用旧的 XMLHttpRequest 浏览器 API 的示例:
// Browser example
function requestURL(url) {
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
// assign event handlers
xhr.addEventListener("load" , () => {
resolve({
status: xhr.status,
text: xhr.responseText
});
});
xhr.addEventListener("error", error => {
reject(error);
});
// send the request
xhr.open( "get" , url);
xhr.send();
});
}
const promise = requestURL("books.json");
// listen for both fulfillment and rejection
promise.then(response => {
// fulfillment
console.log(response.status);
console.log(response.text);
}, reason => {
// rejection
console.error(reason.message);
});
在此示例中,XMLHttpRequest 调用被包装在一个 Promise 中。 load 事件指示请求何时成功完成,因此 promise 执行器在事件处理程序中调用 resolve()。类似地,错误事件指示请求何时无法完成,因此在该事件处理程序中调用 reject() . 您可以按照相同的过程(在事件处理程序中使用 resolve() 和 reject())将基于事件的功能转换为基于承诺的功能。
executor 的一个重要方面是它们在创建 Promise 时立即运行。 在前面的示例中,创建了 xhr 对象,分配了事件处理程序,并在从 requestURL() 返回 Promise 之前启动了调用。 当在执行器内部调用 resolve() 或 reject() 时,promise 的状态和值会立即设置,但所有的 promise 处理程序(作为微任务)在当前脚本作业完成之前不会执行。 例如,考虑一下如果在执行程序中立即调用 resolve() 会发生什么,如下代码所示:
const promise = new Promise((resolve, reject) => {
console.log("Executor");
resolve(42);
});
promise.then(result => {
console.log(result);
});
console.log("Hi!");
在这里,promise 立即解决,没有任何延迟,然后使用 then() 添加一个实现处理程序以输出结果。 即使promise在履行时已经解决添加处理程序后,输出将如下:
Executor
Hi!
42
执行器首先运行,将“Executor
”输出到控制台。 接下来,完成处理程序被分配但不会立即执行。 相反,会创建一个新的微任务以在当前脚本作业之后运行。 这意味着 console.log("Hi!")
在执行处理程序之前执行,在脚本的其余部分完成后输出42
。
一个promise只能被解析一次,所以如果你在一个执行器中多次调用resolve(),第一次之后的每个调用都会被忽略。
执行器错误
如果在 executor 中抛出错误,则调用 promise 的拒绝处理程序。 例如:
const promise = new Promise((resolve, reject) => {
throw new Error("Uh oh!");
});
promise.catch(reason => {
console.log(reason.message); // "Uh oh!"
});
在这段代码中,执行者故意抛出一个错误。 每个执行器内部都有一个隐式的 try-catch,以便捕获错误,然后将其传递给拒绝处理程序。 前面的例子等价于:
const promise = new Promise((resolve, reject) => {
try {
throw new Error("Uh oh!");
} catch (ex) {
reject(ex);
}
});
promise.catch(reason => {
console.log(reason.message); // "Uh oh!"
});
执行器处理捕获任何抛出的错误以简化这个常见用例,就像其他rejection一样,JavaScript 引擎抛出错误并在没有reject handler时停止执行。