promise 是一个单向闩锁。一旦它被一个值解决或被一个原因拒绝,它的状态和值/原因就永远不会改变。所以,无论你对同一个承诺执行多少次.then(),你总是会得到相同的结果。这就是“不可变”的意思。
我不确定您所说的保证值是什么意思。不能保证承诺会永远解决。它可能会拒绝(因此没有值),或者如果操作永远不会完成,它可能永远不会解决或拒绝。
Promise 设计的操作类型的一个示例是异步操作,例如 Ajax 调用或从文件中读取一些字节。该操作是异步的(解释器的正常执行在操作开始后继续)并且操作具有特定的开始和结束。在大多数情况下,操作可能成功完成,在这种情况下它可以有一个值,或者它可能以错误结束,在这种情况下它有一个错误。 value 和 error 都可以是对象,因此如果结果不仅仅是一个简单的值,它们可以有许多属性。
例如,Ajax 调用具有特定的开始和结束。它不能多次结束,因此它是 promise 的完美匹配。您会得到一个表示 ajax 操作最终结果的承诺。然后注册一个完成处理程序和一个拒绝处理程序,当操作完成时将调用其中一个或另一个。
普通回调只是回调,每次调用时都可以赋予不同的值,并且可以多次调用。
如果您希望在某个操作完成并且该操作具有特定的开始和结束时仅收到一次通知,请使用承诺。
如果您想获得多次通知,请使用普通回调或事件侦听器或观察者或其他可以多次触发的机制。
举个简单的例子,setTimeout() 与 Promise 配合得非常好。
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);
});
而且,setInterval() 根本不适用于 Promise,因为它想在每次经过时间间隔时重复通知您,而这根本不适用于 Promise。坚持回调setInterval()。