承诺是一种单向闩锁。一旦它被一个值解决或因一个原因被拒绝,它的状态和值/原因就永远不会改变。所以,无论你做了多少次.then()
同样的承诺,你总会得到同样的结果。这就是“不变”的意思。
我不确定你所说的保证值是什么意思。无法保证承诺会得到解决。它可能会拒绝(因此没有值),或者如果操作永远不会完成,它可能永远不会解析或拒绝。
Promise 所设计的操作类型的一个示例是异步操作,例如 Ajax 调用或从文件中读取一些字节。该操作是异步的(解释器在操作开始后继续正常执行)并且该操作有特定的开始和结束。在大多数情况下,操作可能会成功完成(在这种情况下它可以有一个值),或者可能以错误结束(在这种情况下它有错误)。值和错误都可以是对象,因此如果结果不仅仅是一个简单的值,它们可以具有许多属性。
例如,Ajax 调用具有特定的开始和结束。它不能结束多次,因此它是 Promise 的完美匹配。您会得到一个承诺,表示 ajax 操作的最终结果。然后,您注册一个完成处理程序和一个拒绝处理程序,并且当操作完成时将调用其中之一。
普通回调只是回调,每次调用它们时都可以赋予不同的值,并且可以多次调用它们。
如果您希望在某个操作完成并且该操作具有特定的开始和结束时收到且仅一次通知,请使用 Promise。
如果您想多次收到通知,请使用普通回调或事件侦听器或观察者或其他可以多次触发的机制。
举个简单的例子,setTimeout()
有承诺,效果很好。
function delay(t) {
return new Promise((resolve, reject) => {
resolve();
}, t);
}
// delay 100ms before starting the operation
delay(100).then(run);
或者,使用 Bluebird Promise 库进行更复杂的操作,循环浏览 URL 列表、下载内容、解析内容、在内容中查找某些特定 URL,然后将它们全部收集(也称为抓取):
const Promise = require('bluebird');
const request = Promise.promisifyAll(require('request'), {multiArgs: true});
const cheerio = require('cheerio');
function getAsync() {
return request.getAsync.apply(request, arguments).then(argArray => {
// return only the response html
if (argArray[0].statusCode !== 200) {
throw new Error("response statusCode = " + argArray[0].statusCode);
}
return argArray[1];
});
}
const urls = [....];
Promise.mapSeries(urls, url => {
return getAsync({url: url, gzip: true}).then(html => {
let $ = cheerio.load(html);
let resources = $("#external_resources_list li a.filename");
resources.each(index, link) => {
let href = $(link).attr("href");
console.log(href);
results.push(href);
});
}).catch(err => {
// log error, but keep going
console.log(url, err);
});
}).then(() => {
// got all results here
console.log(results);
});
And, setInterval()
根本不适用于承诺,因为它想在每次时间间隔过去时重复通知您,而这根本不适用于承诺。坚持回调setInterval()
.