ZetCode

JS promise(承诺)

最后修改于 2023 年 10 月 18 日

在本文中,我们将展示如何在 JavaScript 中使用 promises。

Promise 代表一个潜在的值或错误,该值或错误将在未来某个时间点可用。

Promise 可以具有以下状态之一:

我们使用回调函数或 async/await 关键字来处理 promises。

在某些编程语言中,promises 被称为 futures(未来)。

JS Promise.resolve

Promise.resolve 方法返回一个 Promise 对象,该对象以给定的值解析。

main.js
let promise = new Promise(resolve => {

    setTimeout(() => resolve(2), 2000);
});

promise.then(val => console.log(val));

console.log('finished');

我们创建一个 promise,该 promise 在两秒后以一个整数值解析。 then 函数附加回调函数,用于处理 promise 的 resolve 和/或 reject(完成和/或拒绝)。

$ node main.js
finished
2

在下一个示例中,我们使用 async/await 关键字。

main.js
async function doWork() {

    let res = await promise;
    console.log(res);
}

let promise = new Promise(resolve => {

    setTimeout(() => resolve(2), 2000);
});

doWork();

console.log('finished');

await 关键字用于等待一个 Promise。它只能在 async 函数内部使用。

JS promise 错误

Promise.reject 方法返回一个 Promise 对象,该对象以给定的原因被 reject(拒绝)。

main.js
let promise = new Promise((resolve, reject) => {

    let b = Math.random() < 0.3;

    if (b) {
        resolve(10);
    } else {
        reject("promise error");
    }
});

promise.then(val => console.log(val)).catch(err => {
    console.log(`${err}`)
});

console.log('finished');

在示例中,我们使用 Math.random 模拟一个错误。我们使用 catch 方法捕获该错误。

$ node main.js
finished
promise error
$ node main.js
finished
promise error
$ node main.js
finished
10

JS 链式 promise

可以使用链式操作执行多个异步操作。

main.js
let p = new Promise((resolve) => {
    resolve(1);
});

let r = p.then(val => val + 2).then(val => val + 3)
    .then(val => val + 4).then(val => console.log(val));

console.log('finished');

该示例通过链式 promise 添加四个整数。

$ node chain.js
finished
10

JS Promise.all

Promise.all 方法将一个 promises 的可迭代对象作为参数,并返回一个单一的 promise,该 promise 解析为给定 promises 结果的数组。

当所有 promises 都已解析时,此返回的 promise 会解析。如果任何输入 promises 被 rejected(拒绝)并带有错误,它会立即被拒绝。

main.js
const p1 = new Promise((resolve) => setTimeout(resolve, 100, 100));
const p2 = new Promise((resolve) => setTimeout(resolve, 300, 200));
const p3 = new Promise((resolve) => setTimeout(resolve, 500, 300));

const promises = [p1, p2, p3];

Promise.all(promises).then((data) =>
    console.log(data.reduce((total, next) => total + next)));

console.log('finished');

在示例中,我们等待所有 promises 完成,最后,我们计算返回值的总和。

$ node all.js
finished
600

JS 使用 axios 进行多次请求

在下一个示例中,我们使用 axois 库执行多个 get 请求。 Axios 是一个基于 promise 的 HTTP 客户端,适用于 Node 和浏览器。

$ npm i axios

我们安装 Axios 库。

main.js
const axios = require('axios');

async function makeRequests(urls) {

    const fetchUrl = (url) => axios.get(url);
    const promises = urls.map(fetchUrl);

    let responses = await Promise.all(promises);

    responses.forEach(resp => {

        let msg = `${resp.config.url} -> ${resp.headers.server}: ${resp.status}`;
        console.log(msg);
    });
}

let urls = [
    'http://webcode.me',
    'https://example.com',
    'http://httpbin.org',
    'https://clojure.org',
    'https://fsharp.org',
    'https://symfony.com.cn',
    'https://perl.net.cn',
    'https://php.ac.cn',
    'https://pythonlang.cn',
    'https://vscode.js.cn',
    'https://github.com'
];

makeRequests(urls);

我们使用 Promise.all 等待所有请求完成。完成后,我们遍历响应数组、服务器名称和响应状态。

$ node main.js
http://webcode.me -> nginx/1.6.2: 200
https://example.com -> ECS (dcb/7ECA): 200
http://httpbin.org -> gunicorn/19.9.0: 200
https://clojure.org -> AmazonS3: 200
https://fsharp.org -> GitHub.com: 200
https://symfony.com.cn -> cloudflare: 200
https://perl.net.cn -> Combust/Plack (Perl): 200
https://php.ac.cn -> myracloud: 200
https://pythonlang.cn -> nginx: 200
https://vscode.js.cn -> Microsoft-IIS/10.0: 200
https://github.com -> GitHub.com: 200

JS 使用 Puppeteer 创建 PDF

在下面的示例中,我们使用 Puppeteer 库从网页生成 PDF 文件。

$ npm i puppeteer

我们安装 Puppeteer。

main.js
const puppeteer = require('puppeteer');

(async () => {
  const browser = await puppeteer.launch();
  const page = await browser.newPage();
  await page.goto('http://webcode.me');
  await page.pdf({ path: 'webcode.pdf', format: 'a5' });

  await browser.close();
})();

整个任务由几个异步操作组成,这些操作使用 async/await 关键字处理。

来源

JS Promise - 语言参考

在本文中,我们使用 JavaScript 中的 promises。

作者

我叫 Jan Bodnar,是一位充满激情的程序员,拥有丰富的编程经验。自 2007 年以来,我一直在撰写编程文章。迄今为止,我已经撰写了 1,400 多篇文章和 8 本电子书。我拥有超过十年的编程教学经验。

查看 所有 JavaScript 教程。