美文网首页
JS基础(五)

JS基础(五)

作者: a437e8f87a81 | 来源:发表于2022-02-16 10:25 被阅读0次

    // 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基础(五)

          本文链接:https://www.haomeiwen.com/subject/qfpllrtx.html