JS基础(五)

// 1. JS是单线程 解决方式 异步

// 2. 异步的解决方式 事件轮循

// 3. 事件轮循的核心-回调函数

// let arr = [1,34,3]

// let arr2 =  arr.sort()

// setTimeout(() => alert(arr2),6000)

// //同步回调函数 异步回调函数

// console.log(arr)

// 回调

// promise

// 异步编程的一种解决方案,比传统的解决方案-回调函数和事件-更合理

// 三种状态

// pending【待定】初始状态

// fulfilled [实现] 操作成功

// rejected 【拒绝】 操作失败

// Promise 是将“生产者代码”和“消费者代码”连接在一起的一个特殊的 JavaScript 对象。用我们的类比来说:这就是就像是“订阅列表”。“生产者代码”花费它所需的任意长度时间来产出所承诺的结果,而 “promise” 将在它(译注:指的是“生产者代码”,也就是下文所说的 executor)准备好时,将结果向所有订阅了的代码开放。

// 这种类比并不十分准确,因为 JavaScipt 的 promise 比简单的订阅列表更加复杂:它们还拥有其他的功能和局限性。但以此开始挺好的。

// Promise 对象的构造器(constructor)语法如下:

// let promise = new promise(传一个函数)

// let xx = Promise(function (resolve, reject) {

//    resolve(console.log('xxxxx'))

// });

//

// xx.then(function (res)) {

//    console.log("yyyy")

// }

// 传递给 new Promise 的函数被称为 executor。当 new Promise 被创建,executor 会自动运行。它包含最终应产出结果的生产者代码。按照上面的类比:executor 就是“歌手”。

// 它的参数 resolve 和 reject 是由 JavaScript 自身提供的回调。我们的代码仅在 executor 的内部。

// 当 executor 获得了结果,无论是早还是晚都没关系,它应该调用以下回调之一:

// resolve(value) —— 如果任务成功完成并带有结果 value。

// reject(error) —— 如果出现了 error,error 即为 error 对象。

// 所以总结一下就是:executor 会自动运行并尝试执行一项工作。尝试结束后,如果成功则调用 resolve,如果出现 error 则调用 reject。

// 由 new Promise 构造器返回的 promise 对象具有以下内部属性:

// state —— 最初是 "pending",然后在 resolve 被调用时变为 "fulfilled",或者在 reject 被调用时变为 "rejected"。

// result —— 最初是 undefined,然后在 resolve(value) 被调用时变为 value,或者在 reject(error) 被调用时变为 error。

// let promise = new Promise(function (resolve,reject){

//    console.log("no")

//    // 当 promise 被构造完成时,自动执行此函数

//    // 1 秒后发出工作已经被完成的信号,并带有结果 "done"

//    setTimeout(() => resolve(console.log("yes")),1000)

//    console.log("done")

// });

// executor 被自动且立即调用(通过 new Promise)。

// executor 接受两个参数:resolve 和 reject。这些函数由 JavaScipt 引擎预先定义,因此我们不需要创建它们。我们只需要在准备好(译注:指的是 executor 准备好)时调用其中之一即可。

// // 经过 1 秒的“处理”后,executor 调用 resolve("done") 来产生结果。这将改变 promise 对象的状态:

// let promise1 = new Promise(function (resolve, reject) {

//    // 1 秒后发出工作已经被完成的信号,并带有 error

//    setTimeout(() => reject(new Error("Whoops")),1000)

// });

// 对 reject(...) 的调用将 promise 对象的状态移至 "rejected":

// 总而言之,executor 应该执行一项工作(通常是需要花费一些时间的事儿),然后调用 resolve 或 reject 来改变对应的 promise 对象的状态。

// 与最初的 “pending” promise 相反,一个 resolved 或 rejected 的 promise 都会被称为 “settled”。

// 这儿只能有一个结果或一个 error

// executor 只能调用一个 resolve 或一个 reject。任何状态的更改都是最终的。

// 所有其他的再对 resolve 和 reject 的调用都会被忽略:

// 这儿的宗旨是,一个被 executor 完成的工作只能有一个结果或一个 error。

// 并且,resolve/reject 只需要一个参数(或不包含任何参数),并且将忽略额外的参数。

// let promise = new Promise(function(resolve, reject) {

//    resolve("done");

//    reject(new Error("…")); // 被忽略

//    setTimeout(() => resolve("…")); // 被忽略

// });

// 以 Error 对象 reject

// // 如果什么东西出了问题, executor 应该调用 reject。这可以使用任何类型的参数来完成(就像 resolve 一样)。但是建议使用 Error 对象(或继承自 Error 的对象)。这样做的理由很快就会显而易见。

// Resolve/reject 可以立即进行,实际上,executor 通常是异步执行某些操作,并在一段时间后调用 resolve/reject,但这不是必须的。我们还可以立即调用 resolve 或 reject,就像这样:

// let promise = new Promise(function (resolve, reject) {

//    resolve(123)

// })

// 例如,当我们开始做一个任务时,但随后看到一切都已经完成并已被缓存时,可能就会发生这种情况。

// 这挺好。我们立即就有了一个 resolved 的 promise。

// state 和 result 都是内部的

// Promise 对象的 state 和 result 属性都是内部的。我们无法直接访问它们。但我们可以对它们使用 .then/.catch/.finally 方法。我们在下面对这些方法进行了描述。

// 消费者:then,catch,finally

// Promise 对象充当的是 executor(“生产者代码”或“歌手”)和消费函数(“粉丝”)之间的连接,后者将接收结果或 error。可以通过使用 .then、.catch 和 .finally 方法为消费函数进行注册。

// let promise = new Promise(function (resolve, reject) {

//    alert('saaa')

//    setTimeout(() => resolve("done"),3000)

// });

// promise.then(

//    function (resault){

//        alert('xxxx')

//    }

// )

// .then 的第一个参数是一个函数,该函数将在 promise resolved 后运行并接收结果。

// .then 的第二个参数也是一个函数,该函数将在 promise rejected 后运行并接收 error。

// 在 reject 的情况下,运行第二个:

// let promise = new Promise(function (resolve, reject) {

//    setTimeout((() => reject(new Error('xxxx'))),2000)

// })

// promise.then(

//    result = alert(result)

//    error = alert(error)

// )

// let promise = new Promise(function (resolve, reject) {

//    setTimeout(() => resolve('done'),1000)

// })

// promise.then(alert)

// catch

// 如果我们只对 error 感兴趣,那么我们可以使用 null 作为第一个参数:.then(null, errorHandlingFunction)。或者我们也可以使用 .catch(errorHandlingFunction),其实是一样的:

// let promise = Promise(function (resolve, reject) {

//    setTimeout(() => reject(new Error("xxxx")),2000)

// })

// promise.catch(alert)

// 如果我们只对 error 感兴趣,那么我们可以使用 null 作为第一个参数:.then(null, errorHandlingFunction)。或者我们也可以使用 .catch(errorHandlingFunction),其实是一样的:

// catch(f) 调用是 .then(null, f) 的完全的模拟,它只是一个简写形式。

// finally

// new Promise((resolve, reject) => {

//    /* 做一些需要时间的事儿,然后调用 resolve/reject */

// })

//    // 在 promise 为 settled 时运行,无论成功与否

//    .finally(() => stop loading indicator)

// // 所以,加载指示器(loading indicator)始终会在我们处理结果/错误之前停止

// .then(result => show result, err => show error)

// new Promise((resolve, reject) => {

//

// })

//    .finally(() => stop)

//    .then(result => showResault, error => showError)

// finally 处理程序(handler)没有参数。在 finally 中,我们不知道 promise 是否成功。没关系,因为我们的任务通常是执行“常规”的定稿程序(finalizing procedures)。

// finally 处理程序将结果和 error 传递给下一个处理程序。

// 例如,在这儿结果被从 finally 传递给了 then:

// new Promise((resolve, reject) => {

//    setTimeout(() => resolve("result"), 2000)

// })

//    .finally(() => alert("Promise ready"))

//    .then(result => alert(result)); // <-- .then 对结果进行处理

// new Promise((resolve, reject) => {

//    throw new Error("error");

// })

//    .finally(() => alert("Promise ready"))

//    .catch(err => alert(err));  // <-- .catch 对 error 对象进行处理

// 这非常方便,因为 finally 并不是意味着要处理 promise 的结果。所以它将结果传递了下去。

// 如果 promise 为 pending 状态,.then/catch/finally 处理程序(handler)将等待它。否则,如果 promise 已经是 settled 状态,它们就会运行:

// 下面这 promise 在被创建后立即变为 resolved 状态

// let promise = new Promise(resolve => resolve("done!"));

// promise.then(alert); // done!(现在显示)

// 请注意这使得 promise 比现实生活中的“订阅列表”方案强大得多。如果歌手已经发布了他们的单曲,然后某个人在订阅列表上进行了注册,则他们很可能不会收到该单曲。实际生活中的订阅必须在活动开始之前进行。

// Promise 则更加灵活。我们可以随时添加处理程序(handler):如果结果已经在了,它们就会执行。

// function loadScript(src, callback) {

//    let script = document.createElement('script')

//    script.src = src

//    script.onload = () => callback(null, script)

//    script.onerror = () => callback(new Error(`error ${src}`))

//    document.head.append(script)

// }

// 改写

function loadScript(scr) {

return new Promise(function (resolve, reject) {

let script =document.createElement('script')

script.src = src

script.onload = () => resolve(script)

script.onerror = () => reject(new Error(`error ${src}`))

document.head.append(script)

})

}

// 用法

let promise =loadScript("xxxxx")

promise.then(

script =>alert(`${script.src} is loaded!`),

    error =>alert(`Error: ${error.message}`)

)

// promise.then(script => alert('Another handler...'));

// Promises    Callbacks

// Promises 允许我们按照自然顺序进行编码。首先,我们运行 loadScript 和 .then 来处理结果。  在调用 loadScript(script, callback) 时,在我们处理的地方(disposal)必须有一个 callback 函数。换句话说,在调用 loadScript 之前,我们必须知道如何处理结果。

function delay(ms) {

return new Promise(resolve =>setTimeout(resolve, ms));

}

delay(3000).then(() =>alert('runs after 3 seconds'));

// Promise 链

new Promise(function(resolve, reject) {

setTimeout(() => resolve(1), 1000); // (*)

}).then(function(result) {// (**)

    alert(result); // 1

    return result *2;

}).then(function(result) {// (***)

    alert(result); // 2

    return result *2;

}).then(function(result) {

alert(result); // 4

    return result *2;

});

// 它的理念是将 result 通过 .then 处理程序(handler)链进行传递。

// 运行流程如下:

// 初始 promise 在 1 秒后进行 resolve (*),

// 然后 .then 处理程序(handler)被调用 (**)。

// 它返回的值被传入下一个 .then 处理程序(handler)(***)

// ……依此类推。

// 随着 result 在处理程序(handler)链中传递,我们可以看到一系列的 alert 调用:1 → 2 → 4。

// 之所以这么运行,是因为对 promise.then 的调用会返回了一个 promise,所以我们可以在其之上调用下一个 .then。

// 当处理程序(handler)返回一个值时,它将成为该 promise 的 result,所以将使用它调用下一个 .then。

// 新手常犯的一个经典错误:从技术上讲,我们也可以将多个 .then 添加到一个 promise 上。但这并不是 promise 链(chaining)。

// 我们在这里所做的只是一个 promise 的几个处理程序(handler)。它们不会相互传递 result;相反,它们之间彼此独立运行处理任务。

// 这里它的一张示意图(你可以将其与上面的链式调用做一下比较):

// 在同一个 promise 上的所有 .then 获得的结果都相同 — 该 promise 的结果。所以,在上面的代码中,所有 alert 都显示相同的内容:1。

// 实际上我们极少遇到一个 promise 需要多处理程序(handler)的情况。使用链式调用的频率更高。

// let promise = new Promise(function(resolve, reject) {

//    setTimeout(() => resolve(1), 1000);

// });

// promise.then(function(result) {

//    alert(result); // 1

//    return result * 2;

// });

// promise.then(function(result) {

//    alert(result); // 1

//    return result * 2;

// });

// promise.then(function(result) {

//    alert(result); // 1

//    return result * 2;

// });

// .then(handler) 中所使用的处理程序(handler)可以创建并返回一个 promise。

// 在这种情况下,其他的处理程序(handler)将等待它 settled 后再获得其结果(result)。

new Promise(function(resolve, reject) {

setTimeout(() => resolve(1), 1000);

}).then(function(result) {

alert(result); // 1

    return new Promise((resolve, reject) => {// (*)

        setTimeout(() => resolve(result *2), 1000);

    });

}).then(function(result) {// (**)

    alert(result); // 2

    return new Promise((resolve, reject) => {

setTimeout(() => resolve(result *2), 1000);

    });

}).then(function(result) {

alert(result); // 4

});

// 这里第一个 .then 显示 1 并在 (*) 行返回 new Promise(…)。1 秒后它会进行 resolve,然后 result(resolve 的参数,在这里它是 result*2)被传递给第二个 .then 的处理程序(handler)。这个处理程序(handler)位于 (**) 行,它显示 2,并执行相同的动作(action)。

Promise.all()// 所有结果成功

Promise.race()//只要有一个返回不管成功或者失败

你可能感兴趣的:(JS基础(五))