摘要:在本教程中,您将学习有关 JavaScript Promise 链模式的知识,该模式将 Promise 连接起来以按顺序执行异步操作。
JavaScript Promise 链的介绍
有时,您希望执行两个或多个相关的异步操作,其中下一个操作从上一个操作的结果开始。例如
首先,创建一个新的 Promise,它在 3 秒后解析为数字 10
let p = new Promise((resolve, reject) => {
setTimeout(() => {
resolve(10);
}, 3 * 100);
});
Code language: JavaScript (javascript)
请注意,setTimeout()
函数模拟了异步操作。
然后,调用 Promise 的 then()
方法
p.then((result) => {
console.log(result);
return result * 2;
});
Code language: JavaScript (javascript)
传递给 then()
方法的回调在 Promise 解析后执行。在回调中,我们显示 Promise 的结果并返回一个乘以 2 的新值 (result*2
)。
因为 then()
方法返回一个解析为一个值的新的 Promise
,所以您可以在返回的 Promise
上像这样调用 then()
方法
let p = new Promise((resolve, reject) => {
setTimeout(() => {
resolve(10);
}, 3 * 100);
});
p.then((result) => {
console.log(result);
return result * 2;
}).then((result) => {
console.log(result);
return result * 3;
});
Code language: JavaScript (javascript)
输出
10
20
在此示例中,第一个 then()
方法中的返回值被传递给第二个 then()
方法。您可以像这样连续调用 then()
方法
let p = new Promise((resolve, reject) => {
setTimeout(() => {
resolve(10);
}, 3 * 100);
});
p.then((result) => {
console.log(result); // 10
return result * 2;
}).then((result) => {
console.log(result); // 20
return result * 3;
}).then((result) => {
console.log(result); // 60
return result * 4;
});
Code language: JavaScript (javascript)
输出
10
20
60
我们像这样调用 then()
方法的方式通常被称为 Promise 链。
下图说明了 Promise 链

一个 Promise 的多个处理程序
当您多次在 Promise 上调用 then()
方法时,这不是 Promise 链。例如
let p = new Promise((resolve, reject) => {
setTimeout(() => {
resolve(10);
}, 3 * 100);
});
p.then((result) => {
console.log(result); // 10
return result * 2;
})
p.then((result) => {
console.log(result); // 10
return result * 3;
})
p.then((result) => {
console.log(result); // 10
return result * 4;
});
Code language: JavaScript (javascript)
输出
10
10
10
在此示例中,我们对一个 Promise 有多个处理程序。这些处理程序之间没有关系。此外,它们独立执行,并且不像上面的 Promise 链那样将结果从一个传递到另一个。
下图说明了一个拥有多个处理程序的 Promise

在实践中,您很少会对一个 Promise 使用多个处理程序。
返回一个 Promise
当您在 then()
方法中返回一个值时,then()
方法会返回一个立即解析为返回值的新的 Promise
。
此外,您可以在 then()
方法中返回一个新的 Promise,像这样
let p = new Promise((resolve, reject) => {
setTimeout(() => {
resolve(10);
}, 3 * 100);
});
p.then((result) => {
console.log(result);
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(result * 2);
}, 3 * 1000);
});
}).then((result) => {
console.log(result);
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(result * 3);
}, 3 * 1000);
});
}).then(result => console.log(result));
Code language: JavaScript (javascript)
输出
10
20
60
此示例显示了每 3 秒后的 10、20 和 60。这种代码模式允许您按顺序执行一些任务。
以下修改了上面的示例
function generateNumber(num) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(num);
}, 3 * 1000);
});
}
generateNumber(10)
.then((result) => {
console.log(result);
return generateNumber(result * 2);
})
.then((result) => {
console.log(result);
return generateNumber(result * 3);
})
.then((result) => console.log(result));
Code language: JavaScript (javascript)
Promise 链语法
有时,您需要按顺序执行多个异步任务。此外,您需要将上一步的结果传递到下一步。在这种情况下,您可以使用以下语法
step1()
.then(result => step2(result))
.then(result => step3(result))
...
Code language: JavaScript (javascript)
如果您需要将上一步的结果传递到下一步而不传递结果,请使用此语法
step1()
.then(step2)
.then(step3)
...
Code language: CSS (css)
假设您希望按顺序执行以下异步操作
- 首先,从数据库中获取用户。
- 其次,获取所选用户的服务。
- 第三,计算用户服务的服务成本。
以下函数说明了三个异步操作
function getUser(userId) {
return new Promise((resolve, reject) => {
console.log('Get the user from the database.');
setTimeout(() => {
resolve({
userId: userId,
username: 'admin'
});
}, 1000);
})
}
function getServices(user) {
return new Promise((resolve, reject) => {
console.log(`Get the services of ${user.username} from the API.`);
setTimeout(() => {
resolve(['Email', 'VPN', 'CDN']);
}, 3 * 1000);
});
}
function getServiceCost(services) {
return new Promise((resolve, reject) => {
console.log(`Calculate the service cost of ${services}.`);
setTimeout(() => {
resolve(services.length * 100);
}, 2 * 1000);
});
}
Code language: JavaScript (javascript)
以下使用 Promise 来序列化序列
getUser(100)
.then(getServices)
.then(getServiceCost)
.then(console.log);
Code language: CSS (css)
输出
Get the user from the database.
Get the services of admin from the API.
Calculate the service cost of Email,VPN,CDN.
300
Code language: JavaScript (javascript)
请注意,ES2017 引入了 async
/await
,它可以帮助您编写比使用 Promise 链技术更简洁的代码。
在本教程中,您已经学习了 Promise 链,它可以按顺序执行多个异步任务。