ฉันจะรอคำสัญญาให้เสร็จก่อนที่จะส่งคืนตัวแปรของฟังก์ชันได้อย่างไร


149

ฉันยังคงดิ้นรนกับคำมั่นสัญญา แต่ก็มีความคืบหน้าขอบคุณชุมชนที่นี่

ฉันมีฟังก์ชั่น JS ง่าย ๆ ซึ่งสอบถามฐานข้อมูลแยกวิเคราะห์ มันควรจะส่งคืนอาร์เรย์ของผลลัพธ์ แต่เห็นได้ชัดเนื่องจากธรรมชาติของการสืบค้นแบบอะซิงโครนัส

ฉันต้องทำอะไรเพื่อให้ฟังก์ชั่นนี้รอผลของสัญญา?

นี่คือรหัสของฉัน:

function resultsByName(name)
{   
    var Card = Parse.Object.extend("Card");
    var query = new Parse.Query(Card);
    query.equalTo("name", name.toString());

    var resultsArray = [];

    var promise = query.find({
               success: function(results) {
               // results is an array of Parse.Object.
                             console.log(results);
                             //resultsArray = results;
                             return results;
               },

               error: function(error) {
               // error is an instance of Parse.Error.
                             console.log("Error");
               }
    });                           

}

3
คุณอาจพิจารณาใช้ async / await ตอนนี้โหนดสนับสนุน async / รอออกจากกล่องตั้งแต่เวอร์ชั่น 7.6
Viliam Simko

คำตอบ:


66

แทนที่จะส่งคืนresultsArrayคุณส่งคืนสัญญาสำหรับอาร์เรย์ผลลัพธ์และจากนั้นthenบนไซต์การโทร - สิ่งนี้มีประโยชน์เพิ่มเติมของผู้โทรที่รู้ว่าฟังก์ชันกำลังดำเนินการ I / O แบบอะซิงโครนัส การเห็นพ้องด้วยกันใน JavaScript นั้นขึ้นอยู่กับว่าคุณอาจต้องการอ่านคำถามนี้เพื่อให้ได้แนวคิดที่กว้างขึ้น:

function resultsByName(name)
{   
    var Card = Parse.Object.extend("Card");
    var query = new Parse.Query(Card);
    query.equalTo("name", name.toString());

    var resultsArray = [];

    return query.find({});                           

}

// later
resultsByName("Some Name").then(function(results){
    // access results here by chaining to the returned promise
});

คุณสามารถดูตัวอย่างเพิ่มเติมของการใช้คำสัญญาแจงกับแบบสอบถามในโพสต์บล็อกของตัวเองเกี่ยวกับเรื่องนี้


คุณช่วยบอกฉันหน่อยได้ไหมว่าอะไรที่สนับสนุนเรื่องนี้ IE9 รองรับสิ่งนี้หรือไม่
sandrina-p

ใช่ แต่การแยกวิเคราะห์ตัวเองส่วนใหญ่ตายแล้วจึงมี @SandrinaPereira นี่คือการแยกวิเคราะห์รหัสเมฆ
Benjamin Gruenbaum

1
อาดังนั้นนี่ไม่ได้เป็นเพียงจาวาสคริปต์บริสุทธิ์? ฉันกำลังมองหาวิธีในการทำเช่นนี้ (รอฟังก์ชั่นเพื่อเริ่มต้นใหม่ให้เสร็จ) แต่ใช้จาวาสคริปต์ที่บริสุทธิ์ ..
sandrina-p

คำถามนี้เกี่ยวกับการแยกวิเคราะห์รหัสไม่ใช่สัญญา คำสัญญาสามารถทำงานได้ (กับห้องสมุด) ในเบราว์เซอร์ใดก็ได้ Bluebird ทำงานใน IE6 และ netscape 7
Benjamin Gruenbaum

1
ฉันได้อ่านดังนั้นสองวันแล้วและยังคงไม่มีใครแก้ไขได้ คำตอบที่ยอมรับนี้เหมือนกัน ฟังก์ชันส่งคืนสัญญาไม่ใช่ค่าตามที่ OP ร้องขอ ทำไมคำตอบนี้ถูกทำเครื่องหมายว่ายอมรับ?
iGanja

19

ฉันต้องทำอะไรเพื่อให้ฟังก์ชั่นนี้รอผลของสัญญา?

ใช้async/await(ไม่ใช่ส่วนหนึ่งของ ECMA6 แต่สามารถใช้ได้กับ Chrome, Edge, Firefox และ Safari ตั้งแต่ปลายปี 2560 ดูcanIuse )
MDN

    async function waitForPromise() {
        // let result = await any Promise, like:
        let result = await Promise.resolve('this is a sample promise');
    }

เพิ่มเนื่องจากความคิดเห็น: ฟังก์ชั่น async ส่งคืน Promise เสมอและใน TypeScript จะมีลักษณะดังนี้:

    async function waitForPromise(): Promise<string> {
        // let result = await any Promise, like:
        let result = await Promise.resolve('this is a sample promise');
    }

4
ฟังก์ชั่น async จะยังคงส่งคืนวัตถุสัญญาหากถูกเรียกโดยไม่ต้องรอ (หรือในรหัสที่ไม่ใช่แบบอะซิงโครนัส) ตรวจสอบผลลัพธ์ของ console.log (waitForPromise ()) หากคุณไม่แน่ใจ การตรวจสอบของ console.log (ผลลัพธ์) ภายในฟังก์ชั่น async จะพิมพ์สิ่งที่คุณคาดหวัง แต่การกลับมาจากฟังก์ชั่น async จะเกิดขึ้นทันทีโดยไม่ปิดกั้นและส่งคืนสัญญา การปิดกั้นใน javascript มักจะไม่ดีมากเนื่องจากเป็นแอปพลิเคชั่นที่มีเธรดเดียวและการบล็อกจะทำให้ไคลเอนต์ pub / sub อื่น ๆ ของการแจ้งเตือนนำแอปทั้งหมดไปที่หัวเข่า
SRM

1
.net มี. wait () ใน "สัญญา" เช่นคลาสงาน Javascript ขาดคุณสมบัตินี้หรือไม่ ฉันต้องรอก่อนที่จะออกจากเครื่องมือบรรทัดคำสั่งของโหนดที่อาจส่งออกไปยังเครื่องมืออื่น "คอย" ทำงานเฉพาะในฟังก์ชั่น async หมายความว่ามันไม่ทำงานนอกขอบเขตของสัญญา
TamusJRoyce

@SRM ฉันรู้สึกว่าความคิดเห็นของคุณขึ้นอยู่กับการตีความตัวอย่างผิด ๆ - มันเป็นเรื่องเกี่ยวกับสัญญา "ภายใน" การแก้ปัญหา (เป็นตัวอย่างสัญญาที่ง่ายที่สุด) ดังนั้นจึงไม่มีผู้เรียกภายนอกที่คุณระบุไว้ในความคิดเห็นของคุณ ดังนั้นฉันจึงตัดสินใจอัพเดทคำตอบ
Martin Meeser

@TamusJRoyce เดาว่าเป็นคำถามของตัวเอง แต่ฉันคิดว่าใน C # คุณสามารถใช้ Task.ContinueWith (Task) ซึ่งเป็นความคิดเดียวกันกับที่คุณเห็นในคำตอบที่ยอมรับ (ซึ่งเรียกว่า "แล้ว ()")
Martin Meeser

ฉันคิดว่าฉันเห็นตอนนี้ ฉันสามารถรวมสคริปต์ทั้งหมดของฉันไว้ในฟังก์ชัน async ขนาดใหญ่ และเรียกใช้ฟังก์ชันนั้นเป็นบรรทัดสุดท้ายของสคริปต์ของฉัน ฟังก์ชั่นนั้นจะยังคงเป็นแผ่นหม้อไอน้ำเล็กน้อย แต่วิธีที่น้อยกว่าที่ฉันรับรู้ก่อนหน้านี้ ฉันไม่คุ้นเคยกับการเขียนฟังก์ชั่นภายในฟังก์ชั่น ขอบคุณ @MartinMeeser!
TamusJRoyce

3

คุณไม่ต้องการให้ฟังก์ชันรอเนื่องจาก JavaScript มีวัตถุประสงค์เพื่อไม่บล็อก ค่อนข้างกลับสัญญาในตอนท้ายของฟังก์ชั่นแล้วฟังก์ชั่นการโทรสามารถใช้สัญญาที่จะได้รับการตอบสนองของเซิร์ฟเวอร์

var promise = query.find(); 
return promise; 

//Or return query.find(); 

1
สิ่งที่คุณโทรกลับด้วยsuccess:บิตถูกปิด
Benjamin Gruenbaum

return query.find();หรือดีกว่า:
บด

ยังโอเค ฉันจะปล่อยให้มันเป็นแบบนี้เพื่อเป็นตัวอย่าง แต่เพิ่มไว้เป็นความคิดเห็น
ติดตาม

ฉันลองสิ่งนี้ แต่ผลลัพธ์ดูเหมือนจะไม่ได้กำหนด resultsByName ("ชื่อ") จากนั้น (ฟังก์ชัน (ผลลัพธ์) {console.log ("มีอาร์เรย์" + results.count);});
mac_55

1
ขอบคุณต้องมีข้อผิดพลาดบางอย่างในฟังก์ชันผลลัพธ์ มันใช้งานได้แล้ว ผมเปลี่ยน console.log ของฉันไป results.length และจะเห็นว่ามี 1 รายการในอาร์เรย์กลับของฉัน :)
mac_55

2

คุณไม่ได้ใช้สัญญาที่นี่ แยกวิเคราะห์ช่วยให้คุณใช้โทรกลับหรือสัญญา; ทางเลือกของคุณ.

หากต้องการใช้สัญญาให้ทำดังต่อไปนี้:

query.find().then(function() {
    console.log("success!");
}, function() {
    console.log("error");
});

ตอนนี้เพื่อดำเนินการสิ่งต่าง ๆ หลังจากสัญญาเสร็จสมบูรณ์คุณสามารถดำเนินการได้ภายในการโทรกลับสัญญาภายในการthen()โทร จนถึงตอนนี้จะเหมือนกับการเรียกกลับปกติ

เมื่อต้องการใช้ประโยชน์จากคำสัญญาให้ดีก็คือเมื่อคุณโยงมันเข้ากับสิ่งเหล่านี้:

query.find().then(function() {
    console.log("success!");

    return new Parse.Query(Obj).get("sOmE_oBjEcT");
}, function() {
    console.log("error");
}).then(function() {
    console.log("success on second callback!");
}, function() {
    console.log("error on second callback");
});

วัตถุผลลัพธ์ประเภทใดเป็นวัตถุ เนื่องจากดูเหมือนว่าไม่มีชุดข้อมูลของฉัน
mac_55

มันควรจะเป็นอาร์เรย์ของParse.Object's
บด
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.